@burdenoff/microfe-housingvista 2026.709.2 → 2026.709.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/housingvista/HousingVistaRoutes.d.ts.map +1 -1
  2. package/dist/housingvista/HousingVistaRoutes.js +136 -37
  3. package/dist/housingvista/HousingVistaRoutes.js.map +1 -1
  4. package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts +1 -1
  5. package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts.map +1 -1
  6. package/dist/housingvista/hooks/useHousingVistaAnalytics.js +4 -4
  7. package/dist/housingvista/hooks/useHousingVistaAnalytics.js.map +1 -1
  8. package/dist/housingvista/pages/amc/AMCManagementPage.d.ts.map +1 -1
  9. package/dist/housingvista/pages/amc/AMCManagementPage.js +62 -60
  10. package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
  11. package/dist/housingvista/pages/assets/AssetDetailPage.d.ts.map +1 -1
  12. package/dist/housingvista/pages/assets/AssetDetailPage.js +141 -138
  13. package/dist/housingvista/pages/assets/AssetDetailPage.js.map +1 -1
  14. package/dist/housingvista/pages/assets/AssetManagementPage.d.ts.map +1 -1
  15. package/dist/housingvista/pages/assets/AssetManagementPage.js +193 -191
  16. package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
  17. package/dist/housingvista/pages/chat/ChatPage.d.ts.map +1 -1
  18. package/dist/housingvista/pages/chat/ChatPage.js +115 -113
  19. package/dist/housingvista/pages/chat/ChatPage.js.map +1 -1
  20. package/dist/housingvista/pages/finance/HomeLoanDetailPage.d.ts.map +1 -1
  21. package/dist/housingvista/pages/finance/HomeLoanDetailPage.js +152 -149
  22. package/dist/housingvista/pages/finance/HomeLoanDetailPage.js.map +1 -1
  23. package/dist/housingvista/pages/finance/HomeLoansPage.d.ts.map +1 -1
  24. package/dist/housingvista/pages/finance/HomeLoansPage.js +141 -139
  25. package/dist/housingvista/pages/finance/HomeLoansPage.js.map +1 -1
  26. package/dist/housingvista/pages/investments/InvestmentDetailPage.d.ts.map +1 -1
  27. package/dist/housingvista/pages/investments/InvestmentDetailPage.js +290 -287
  28. package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
  29. package/dist/housingvista/pages/investments/InvestmentsPage.d.ts.map +1 -1
  30. package/dist/housingvista/pages/investments/InvestmentsPage.js +64 -62
  31. package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
  32. package/dist/housingvista/pages/legal/LegalPage.d.ts.map +1 -1
  33. package/dist/housingvista/pages/legal/LegalPage.js +95 -93
  34. package/dist/housingvista/pages/legal/LegalPage.js.map +1 -1
  35. package/dist/housingvista/pages/legal/LegalServiceDetailPage.d.ts.map +1 -1
  36. package/dist/housingvista/pages/legal/LegalServiceDetailPage.js +129 -126
  37. package/dist/housingvista/pages/legal/LegalServiceDetailPage.js.map +1 -1
  38. package/dist/housingvista/pages/market/AreaInsightsPage.d.ts.map +1 -1
  39. package/dist/housingvista/pages/market/AreaInsightsPage.js +99 -97
  40. package/dist/housingvista/pages/market/AreaInsightsPage.js.map +1 -1
  41. package/dist/housingvista/pages/market/MarketAnalyticsPage.d.ts.map +1 -1
  42. package/dist/housingvista/pages/market/MarketAnalyticsPage.js +138 -136
  43. package/dist/housingvista/pages/market/MarketAnalyticsPage.js.map +1 -1
  44. package/dist/housingvista/pages/marketplace/MarketplacePage.d.ts.map +1 -1
  45. package/dist/housingvista/pages/marketplace/MarketplacePage.js +99 -97
  46. package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
  47. package/dist/housingvista/pages/marketplace/ServiceDetailPage.d.ts.map +1 -1
  48. package/dist/housingvista/pages/marketplace/ServiceDetailPage.js +137 -134
  49. package/dist/housingvista/pages/marketplace/ServiceDetailPage.js.map +1 -1
  50. package/dist/housingvista/pages/offers/OffersPage.d.ts.map +1 -1
  51. package/dist/housingvista/pages/offers/OffersPage.js +94 -92
  52. package/dist/housingvista/pages/offers/OffersPage.js.map +1 -1
  53. package/dist/housingvista/pages/properties/AddPropertyPage.d.ts.map +1 -1
  54. package/dist/housingvista/pages/properties/AddPropertyPage.js +280 -279
  55. package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
  56. package/dist/housingvista/pages/rental/RentalManagementPage.d.ts.map +1 -1
  57. package/dist/housingvista/pages/rental/RentalManagementPage.js +153 -151
  58. package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
  59. package/dist/housingvista/pages/settings/ProfilePage.d.ts.map +1 -1
  60. package/dist/housingvista/pages/settings/ProfilePage.js +52 -50
  61. package/dist/housingvista/pages/settings/ProfilePage.js.map +1 -1
  62. package/dist/housingvista/pages/settings/SettingsPage.d.ts.map +1 -1
  63. package/dist/housingvista/pages/settings/SettingsPage.js +54 -52
  64. package/dist/housingvista/pages/settings/SettingsPage.js.map +1 -1
  65. package/dist/housingvista/pages/shortlist/ShortlistPage.d.ts.map +1 -1
  66. package/dist/housingvista/pages/shortlist/ShortlistPage.js +43 -41
  67. package/dist/housingvista/pages/shortlist/ShortlistPage.js.map +1 -1
  68. package/dist/housingvista/pages/transactions/TransactionDetailPage.d.ts.map +1 -1
  69. package/dist/housingvista/pages/transactions/TransactionDetailPage.js +211 -208
  70. package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
  71. package/dist/housingvista/pages/transactions/TransactionsPage.d.ts.map +1 -1
  72. package/dist/housingvista/pages/transactions/TransactionsPage.js +85 -83
  73. package/dist/housingvista/pages/transactions/TransactionsPage.js.map +1 -1
  74. package/dist/housingvista/pages/verification/VerificationDetailPage.d.ts.map +1 -1
  75. package/dist/housingvista/pages/verification/VerificationDetailPage.js +25 -22
  76. package/dist/housingvista/pages/verification/VerificationDetailPage.js.map +1 -1
  77. package/dist/housingvista/pages/verification/VerificationPage.d.ts.map +1 -1
  78. package/dist/housingvista/pages/verification/VerificationPage.js +123 -121
  79. package/dist/housingvista/pages/verification/VerificationPage.js.map +1 -1
  80. package/dist/housingvista/pages/viewings/ViewingsPage.d.ts.map +1 -1
  81. package/dist/housingvista/pages/viewings/ViewingsPage.js +128 -126
  82. package/dist/housingvista/pages/viewings/ViewingsPage.js.map +1 -1
  83. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RentalManagementPage.js","names":[],"sources":["../../../../src/housingvista/pages/rental/RentalManagementPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect, type FormEvent } from 'react';\nimport {\n Home,\n Users,\n DollarSign,\n TrendingUp,\n Plus,\n FileText,\n CheckCircle,\n XCircle,\n AlertCircle,\n Clock,\n Wrench,\n} from 'lucide-react';\nimport {\n Button,\n EmphasisPanel,\n NextSteps,\n Pagination,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts';\nimport { PageLayout } from '../../components';\nimport { StatCard } from '../../components';\nimport { ChartCard } from '../../components';\nimport { DataTable, type Column } from '../../components';\nimport { StatusBadge } from '../../components';\nimport { FilterBar } from '../../components';\nimport { EmptyState } from '../../components';\nimport {\n useRentalUnits,\n useCreateRentalUnit,\n useCreateMaintenanceRequest,\n useMaintenanceRequests,\n useResolveMaintenanceRequest,\n useRentalApplications,\n useReviewRentalApplication,\n} from '../../hooks';\nimport type { MaintenanceRequestRow, RentalApplicationRow } from '../../hooks';\nimport { useServerPagination } from '../../hooks/useServerPagination';\nimport { formatCurrency, formatDate } from '../../utils/helpers';\nimport { notify } from '../../lib/toast';\nimport type { RentalUnit } from '../../types';\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// Payment-status colours: success / warning / error semantic status tokens.\nconst PAID_COLOR = 'var(--color-status-success-text)';\nconst PENDING_COLOR = 'var(--color-status-warning-text)';\nconst OVERDUE_COLOR = 'var(--color-status-error-text)';\nconst rentTooltipStyle: React.CSSProperties = {\n background: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 10,\n fontSize: 12,\n boxShadow: '0 8px 24px rgb(0 0 0 / 0.12)',\n};\nconst textareaClass =\n '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\ntype RentalStatus = 'occupied' | 'vacant' | 'notice_period' | 'maintenance';\ntype PaymentStatus = 'paid' | 'pending' | 'overdue';\n\nfunction toIso(value: string): string {\n return value ? new Date(value).toISOString() : '';\n}\n\nfunction getStatusVariant(status: RentalUnit['status']): 'success' | 'warning' | 'error' | 'info' | 'muted' {\n switch (status) {\n case 'occupied':\n return 'success';\n case 'vacant':\n return 'warning';\n case 'notice_period':\n return 'info';\n case 'maintenance':\n return 'error';\n default:\n return 'muted';\n }\n}\n\nfunction getPaymentVariant(status: RentalUnit['paymentStatus']): 'success' | 'warning' | 'error' | 'muted' {\n switch (status) {\n case 'paid':\n return 'success';\n case 'pending':\n return 'warning';\n case 'overdue':\n return 'error';\n default:\n return 'muted';\n }\n}\n\nfunction getApplicationVariant(\n status: RentalApplicationRow['status']\n): 'success' | 'warning' | 'error' | 'info' | 'muted' {\n switch (status) {\n case 'approved':\n return 'success';\n case 'rejected':\n return 'error';\n case 'screening':\n return 'warning';\n case 'submitted':\n return 'info';\n default:\n return 'muted';\n }\n}\n\nfunction getMaintenanceVariant(status: MaintenanceRequestRow['status']): 'success' | 'warning' | 'info' | 'muted' {\n switch (status) {\n case 'resolved':\n return 'success';\n case 'in_progress':\n return 'info';\n case 'open':\n return 'warning';\n default:\n return 'muted';\n }\n}\n\nfunction getPriorityVariant(priority: MaintenanceRequestRow['priority']): 'error' | 'warning' | 'muted' {\n switch (priority) {\n case 'high':\n return 'error';\n case 'medium':\n return 'warning';\n default:\n return 'muted';\n }\n}\n\nexport function RentalManagementPage() {\n const pagination = useServerPagination(10);\n const [search, setSearch] = useState('');\n const [debouncedSearch, setDebouncedSearch] = useState('');\n\n // Debounce the search box into the server filter (300ms).\n useEffect(() => {\n const handle = setTimeout(() => setDebouncedSearch(search), 300);\n return () => clearTimeout(handle);\n }, [search]);\n\n const { data: rentalUnits, loading } = useRentalUnits({\n filter: { search: debouncedSearch.trim() || undefined },\n pagination: pagination.pagination,\n });\n\n const handleSearchChange = (value: string) => {\n setSearch(value);\n pagination.setPage(1);\n };\n\n const { createRentalUnit, loading: creating } = useCreateRentalUnit();\n const { createMaintenanceRequest, loading: submittingMaint } = useCreateMaintenanceRequest();\n\n // ---- Maintenance requests (list + resolve) ----\n const maintListPagination = useServerPagination(5);\n const {\n data: maintenanceRequests,\n loading: maintListLoading,\n refetch: refetchMaintenance,\n } = useMaintenanceRequests({ pagination: maintListPagination.pagination });\n const { resolveMaintenanceRequest, loading: resolving } = useResolveMaintenanceRequest();\n\n const [resolveOpen, setResolveOpen] = useState(false);\n const [resolveTarget, setResolveTarget] = useState<MaintenanceRequestRow | null>(null);\n const [resolutionNotes, setResolutionNotes] = useState('');\n\n // ---- Rental applications (landlord review surface) ----\n const appPagination = useServerPagination(5);\n const [appStatus, setAppStatus] = useState<'all' | 'submitted' | 'screening' | 'approved' | 'rejected'>('all');\n const { data: applications, loading: applicationsLoading } = useRentalApplications({\n filter: { status: appStatus === 'all' ? undefined : appStatus },\n pagination: appPagination.pagination,\n });\n const { reviewRentalApplication, loading: reviewing } = useReviewRentalApplication();\n\n const [reviewOpen, setReviewOpen] = useState(false);\n const [reviewTarget, setReviewTarget] = useState<RentalApplicationRow | null>(null);\n const [reviewDecision, setReviewDecision] = useState<'approved' | 'rejected'>('approved');\n const [reviewNotes, setReviewNotes] = useState('');\n\n // Add-tenant dialog state\n const [createOpen, setCreateOpen] = useState(false);\n const [propertyTitle, setPropertyTitle] = useState('');\n const [unitNumber, setUnitNumber] = useState('');\n const [tenantName, setTenantName] = useState('');\n const [tenantEmail, setTenantEmail] = useState('');\n const [tenantPhone, setTenantPhone] = useState('');\n const [monthlyRent, setMonthlyRent] = useState('');\n const [leaseStart, setLeaseStart] = useState('');\n const [leaseEnd, setLeaseEnd] = useState('');\n const [status, setStatus] = useState<RentalStatus>('occupied');\n const [paymentStatus, setPaymentStatus] = useState<PaymentStatus>('pending');\n const [securityDeposit, setSecurityDeposit] = useState('');\n\n // Maintenance dialog state\n const [maintOpen, setMaintOpen] = useState(false);\n const [maintUnit, setMaintUnit] = useState<RentalUnit | null>(null);\n const [maintTitle, setMaintTitle] = useState('');\n const [maintDescription, setMaintDescription] = useState('');\n const [maintCategory, setMaintCategory] = useState('plumbing');\n const [maintPriority, setMaintPriority] = useState<'low' | 'medium' | 'high'>('medium');\n\n const resetCreateForm = () => {\n setPropertyTitle('');\n setUnitNumber('');\n setTenantName('');\n setTenantEmail('');\n setTenantPhone('');\n setMonthlyRent('');\n setLeaseStart('');\n setLeaseEnd('');\n setStatus('occupied');\n setPaymentStatus('pending');\n setSecurityDeposit('');\n };\n\n const openCreate = () => {\n resetCreateForm();\n setCreateOpen(true);\n };\n\n const handleCreate = async (e: FormEvent) => {\n e.preventDefault();\n const rent = Number(monthlyRent);\n if (!propertyTitle.trim() || !unitNumber.trim() || !tenantName.trim() || !tenantEmail.trim()) {\n notify.warning('Missing details', 'Property, unit, tenant name and email are required.');\n return;\n }\n if (!Number.isFinite(rent) || rent <= 0) {\n notify.warning('Enter a valid monthly rent');\n return;\n }\n const deposit = securityDeposit.trim() ? Number(securityDeposit) : undefined;\n try {\n await createRentalUnit({\n propertyTitle: propertyTitle.trim(),\n unitNumber: unitNumber.trim(),\n tenantName: tenantName.trim(),\n tenantEmail: tenantEmail.trim(),\n tenantPhone: tenantPhone.trim() || undefined,\n monthlyRent: rent,\n leaseStart: toIso(leaseStart),\n leaseEnd: toIso(leaseEnd),\n status,\n paymentStatus,\n securityDeposit: deposit !== undefined && Number.isFinite(deposit) ? deposit : undefined,\n });\n notify.success('Rental unit added', `${tenantName.trim()} added to ${propertyTitle.trim()}.`);\n setCreateOpen(false);\n resetCreateForm();\n } catch (err) {\n notify.error('Could not add rental unit', (err as Error).message);\n }\n };\n\n const openMaintenance = (unit: RentalUnit) => {\n setMaintUnit(unit);\n setMaintTitle('');\n setMaintDescription('');\n setMaintCategory('plumbing');\n setMaintPriority('medium');\n setMaintOpen(true);\n };\n\n const handleMaintenance = async (e: FormEvent) => {\n e.preventDefault();\n if (!maintUnit) return;\n if (!maintTitle.trim()) {\n notify.warning('Add a short title for the request');\n return;\n }\n try {\n await createMaintenanceRequest({\n rentalUnitId: maintUnit.id,\n title: maintTitle.trim(),\n description: maintDescription.trim() || undefined,\n category: maintCategory,\n priority: maintPriority,\n });\n notify.success(\n 'Maintenance request logged',\n `Raised for ${maintUnit.propertyTitle}, unit ${maintUnit.unitNumber}.`\n );\n setMaintOpen(false);\n setMaintUnit(null);\n await refetchMaintenance();\n } catch (err) {\n notify.error('Could not log maintenance request', (err as Error).message);\n }\n };\n\n const openResolve = (request: MaintenanceRequestRow) => {\n setResolveTarget(request);\n setResolutionNotes('');\n setResolveOpen(true);\n };\n\n const handleResolve = async (e: FormEvent) => {\n e.preventDefault();\n if (!resolveTarget) return;\n try {\n await resolveMaintenanceRequest(resolveTarget.id, resolutionNotes.trim() || undefined);\n notify.success('Request resolved', `\"${resolveTarget.title}\" was marked resolved.`);\n setResolveOpen(false);\n setResolveTarget(null);\n } catch (err) {\n notify.error('Could not resolve request', (err as Error).message);\n }\n };\n\n const openReview = (application: RentalApplicationRow, decision: 'approved' | 'rejected') => {\n setReviewTarget(application);\n setReviewDecision(decision);\n setReviewNotes('');\n setReviewOpen(true);\n };\n\n const handleReview = async (e: FormEvent) => {\n e.preventDefault();\n if (!reviewTarget) return;\n try {\n await reviewRentalApplication(reviewTarget.id, {\n decision: reviewDecision,\n reviewNotes: reviewNotes.trim() || undefined,\n });\n notify.success(\n reviewDecision === 'approved' ? 'Application approved' : 'Application rejected',\n `${reviewTarget.applicantName}'s application was ${reviewDecision}.`\n );\n setReviewOpen(false);\n setReviewTarget(null);\n } catch (err) {\n notify.error('Could not update application', (err as Error).message);\n }\n };\n\n const stats = useMemo(() => {\n const totalUnits = rentalUnits.length;\n const occupied = rentalUnits.filter((u) => u.status === 'occupied').length;\n const vacant = rentalUnits.filter((u) => u.status === 'vacant').length;\n const monthlyIncome = rentalUnits\n .filter((u) => u.status === 'occupied' || u.status === 'notice_period')\n .reduce((sum, u) => sum + u.monthlyRent, 0);\n return { totalUnits, occupied, vacant, monthlyIncome };\n }, [rentalUnits]);\n\n const rentCollectionStats = useMemo(() => {\n const paid = rentalUnits.filter((u) => u.paymentStatus === 'paid').length;\n const pending = rentalUnits.filter((u) => u.paymentStatus === 'pending').length;\n const overdue = rentalUnits.filter((u) => u.paymentStatus === 'overdue').length;\n const collectionRate = rentalUnits.length > 0 ? (paid / rentalUnits.length) * 100 : 0;\n const collectedRent = rentalUnits\n .filter((u) => u.paymentStatus === 'paid')\n .reduce((sum, u) => sum + u.monthlyRent, 0);\n const outstandingRent = rentalUnits\n .filter((u) => u.paymentStatus === 'pending' || u.paymentStatus === 'overdue')\n .reduce((sum, u) => sum + u.monthlyRent, 0);\n return { paid, pending, overdue, collectionRate, collectedRent, outstandingRent };\n }, [rentalUnits]);\n\n // Real payment-status breakdown for the collection donut (page-scoped, like the tiles).\n const rentCollectionChart = useMemo(\n () =>\n [\n { name: 'Paid', value: rentCollectionStats.paid, color: PAID_COLOR },\n { name: 'Pending', value: rentCollectionStats.pending, color: PENDING_COLOR },\n { name: 'Overdue', value: rentCollectionStats.overdue, color: OVERDUE_COLOR },\n ].filter((slice) => slice.value > 0),\n [rentCollectionStats]\n );\n\n const tenantColumns: Column<RentalUnit>[] = [\n {\n key: 'unitNumber',\n header: 'Unit',\n render: (item) => (\n <div>\n <div className=\"font-medium text-text-primary\">{item.propertyTitle}</div>\n <div className=\"text-xs text-text-secondary\">Unit {item.unitNumber}</div>\n </div>\n ),\n },\n {\n key: 'tenantName',\n header: 'Tenant',\n render: (item) =>\n item.tenantName ? (\n <div>\n <div className=\"font-medium text-text-primary\">{item.tenantName}</div>\n <div className=\"text-xs text-text-secondary\">{item.tenantEmail}</div>\n </div>\n ) : (\n <span className=\"text-text-secondary\">-</span>\n ),\n },\n {\n key: 'leaseStart',\n header: 'Lease Start',\n render: (item) =>\n item.leaseStart ? (\n <span className=\"text-sm text-text-primary\">{formatDate(item.leaseStart)}</span>\n ) : (\n <span className=\"text-text-secondary\">-</span>\n ),\n },\n {\n key: 'leaseEnd',\n header: 'Lease End',\n render: (item) =>\n item.leaseEnd ? (\n <span className=\"text-sm text-text-primary\">{formatDate(item.leaseEnd)}</span>\n ) : (\n <span className=\"text-text-secondary\">-</span>\n ),\n },\n {\n key: 'monthlyRent',\n header: 'Rent',\n render: (item) => <span className=\"font-medium text-text-primary\">{formatCurrency(item.monthlyRent)}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n render: (item) => (\n <div className=\"flex flex-col gap-1\">\n <StatusBadge label={item.status.replace('_', ' ')} variant={getStatusVariant(item.status)} />\n <StatusBadge label={item.paymentStatus} variant={getPaymentVariant(item.paymentStatus)} />\n </div>\n ),\n },\n {\n key: 'actions',\n header: '',\n render: (item) => (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => openMaintenance(item)} className=\"gap-1.5\">\n <Wrench className=\"h-3.5 w-3.5\" />\n Maintenance\n </Button>\n ),\n },\n ];\n\n return (\n <PageLayout\n title=\"Rental Management\"\n description=\"Comprehensive property and tenant management dashboard\"\n purpose=\"Run your rentals as a business — track which units are occupied or vacant, who your tenants are, what rent is collected versus outstanding, and what needs action. Use it to chase late payments, fill vacancies, and keep leases current.\"\n actions={\n <Button type=\"button\" onClick={openCreate} className=\"gap-2\">\n <Plus className=\"h-4 w-4\" />\n Add Tenant\n </Button>\n }\n >\n <NextSteps\n storageKey=\"housingvista-rental\"\n steps={[\n {\n id: 'collection',\n label: 'Check rent collection',\n description: `${rentCollectionStats.overdue} overdue, ${rentCollectionStats.pending} pending — review who still owes.`,\n href: '#rental-collection',\n },\n {\n id: 'tenants',\n label: 'Find a tenant',\n description: 'Search the tenant directory to review leases and contacts.',\n href: '#rental-tenants',\n },\n ]}\n />\n\n {/* Stats Row — primary insight zone (one EmphasisPanel per page) */}\n <EmphasisPanel className=\"p-4\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard label=\"Total Units\" value={stats.totalUnits} icon={<Home className=\"h-4 w-4\" />} />\n <StatCard label=\"Occupied\" value={stats.occupied} icon={<Users className=\"h-4 w-4\" />} />\n <StatCard label=\"Vacant\" value={stats.vacant} icon={<Home className=\"h-4 w-4\" />} />\n <StatCard\n label=\"Monthly Income\"\n value={stats.monthlyIncome}\n prefix=\"$\"\n icon={<DollarSign className=\"h-4 w-4\" />}\n />\n </div>\n </EmphasisPanel>\n\n {/* Rent Collection Section — status donut + real collection tiles */}\n <div id=\"rental-collection\" className=\"scroll-mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <ChartCard title=\"Rent Collection\" description=\"This page's units by payment status\" className=\"lg:col-span-1\">\n {rentCollectionChart.length > 0 ? (\n <div className=\"relative h-52 w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <PieChart>\n <Pie\n data={rentCollectionChart}\n dataKey=\"value\"\n nameKey=\"name\"\n innerRadius={54}\n outerRadius={80}\n paddingAngle={2}\n stroke=\"var(--color-bg-surface)\"\n strokeWidth={2}\n >\n {rentCollectionChart.map((slice) => (\n <Cell key={slice.name} fill={slice.color} />\n ))}\n </Pie>\n <Tooltip\n contentStyle={rentTooltipStyle}\n formatter={(value: number, name) => [`${value} ${value === 1 ? 'unit' : 'units'}`, name]}\n />\n </PieChart>\n </ResponsiveContainer>\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center\">\n <span className=\"text-2xl font-bold text-text-primary\">\n {rentCollectionStats.collectionRate.toFixed(0)}%\n </span>\n <span className=\"text-xs text-text-secondary\">collected</span>\n </div>\n </div>\n ) : (\n <div className=\"flex h-52 items-center justify-center text-sm text-text-secondary\">\n No payment data on this page yet.\n </div>\n )}\n </ChartCard>\n\n <div className=\"lg:col-span-2\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"flex items-center gap-3 rounded-lg bg-status-success-bg-subtle p-4\">\n <CheckCircle className=\"h-5 w-5 text-status-success-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Paid</p>\n <p className=\"text-xl font-bold text-status-success-text\">{rentCollectionStats.paid}</p>\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(rentCollectionStats.collectedRent)} collected\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-lg bg-status-warning-bg-subtle p-4\">\n <Clock className=\"h-5 w-5 text-status-warning-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Pending</p>\n <p className=\"text-xl font-bold text-status-warning-text\">{rentCollectionStats.pending}</p>\n <p className=\"text-xs text-text-secondary\">awaiting payment</p>\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-lg bg-status-error-bg-subtle p-4\">\n <AlertCircle className=\"h-5 w-5 text-status-error-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Overdue</p>\n <p className=\"text-xl font-bold text-status-error-text\">{rentCollectionStats.overdue}</p>\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(rentCollectionStats.outstandingRent)} outstanding\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-lg bg-status-info-bg-subtle p-4\">\n <TrendingUp className=\"h-5 w-5 text-status-info-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Collection Rate</p>\n <p className=\"text-xl font-bold text-status-info-text\">\n {rentCollectionStats.collectionRate.toFixed(0)}%\n </p>\n <p className=\"text-xs text-text-secondary\">of units paid</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {/* Rental Applications — landlord review surface */}\n <div\n id=\"rental-applications\"\n className=\"scroll-mt-6 rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-sm\"\n >\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-3\">\n <h3 className=\"flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <FileText className=\"h-5 w-5\" />\n Rental Applications\n </h3>\n <div className=\"flex flex-wrap items-center gap-2\">\n {(['all', 'submitted', 'screening', 'approved', 'rejected'] as const).map((value) => (\n <button\n key={value}\n type=\"button\"\n onClick={() => {\n setAppStatus(value);\n appPagination.setPage(1);\n }}\n className={`rounded-md px-3 py-1.5 text-xs font-medium capitalize transition-colors ${\n appStatus === value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n }`}\n >\n {value}\n </button>\n ))}\n </div>\n </div>\n {applications.length > 0 ? (\n <>\n <ul className=\"space-y-3\">\n {applications.map((application) => (\n <li\n key={application.id}\n className=\"flex flex-col gap-3 rounded-lg border border-border-subtle p-4 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium text-text-primary\">{application.applicantName}</p>\n <StatusBadge label={application.status} variant={getApplicationVariant(application.status)} />\n </div>\n <p className=\"truncate text-xs text-text-secondary\">{application.applicantEmail}</p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {application.rentalUnit\n ? `${application.rentalUnit.propertyTitle}, unit ${application.rentalUnit.unitNumber}`\n : 'Unit unavailable'}\n {application.monthlyIncome != null\n ? ` · Income ${formatCurrency(application.monthlyIncome)}`\n : ''}\n {application.moveInDate ? ` · Move-in ${formatDate(application.moveInDate)}` : ''}\n </p>\n </div>\n {application.status === 'submitted' || application.status === 'screening' ? (\n <div className=\"flex shrink-0 items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => openReview(application, 'rejected')}\n className=\"gap-1.5\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Reject\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => openReview(application, 'approved')}\n className=\"gap-1.5\"\n >\n <CheckCircle className=\"h-3.5 w-3.5\" />\n Approve\n </Button>\n </div>\n ) : (\n <span className=\"shrink-0 text-xs text-text-secondary\">\n {application.reviewedAt ? `Reviewed ${formatDate(application.reviewedAt)}` : 'Reviewed'}\n </span>\n )}\n </li>\n ))}\n </ul>\n <div className=\"mt-4\">\n <Pagination\n page={appPagination.page}\n pageSize={appPagination.pageSize}\n hasNextPage={applications.length >= appPagination.pageSize}\n hasPreviousPage={appPagination.page > 1}\n onPageChange={appPagination.setPage}\n onPageSizeChange={appPagination.setPageSize}\n />\n </div>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<FileText className=\"h-10 w-10\" />}\n title=\"No applications\"\n description={\n applicationsLoading\n ? 'Loading applications…'\n : 'Rental applications from prospective tenants will appear here for review.'\n }\n className=\"border-0 bg-transparent p-4\"\n />\n )}\n </div>\n\n {/* Tenant List */}\n <div id=\"rental-tenants\" className=\"scroll-mt-6\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Tenant Directory</h2>\n <FilterBar\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder=\"Search units, tenants...\"\n />\n <div className=\"mt-4\">\n {rentalUnits.length > 0 ? (\n <DataTable\n columns={tenantColumns}\n data={rentalUnits}\n keyField=\"id\"\n pageSize={10}\n serverPagination={{\n page: pagination.page,\n pageSize: pagination.pageSize,\n hasNextPage: rentalUnits.length >= pagination.pageSize,\n loading,\n onPageChange: pagination.setPage,\n onPageSizeChange: pagination.setPageSize,\n }}\n />\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n icon={<Users className=\"h-12 w-12\" />}\n title=\"No rental units found\"\n description=\"Try adjusting your search criteria or add a new tenant.\"\n action={\n <Button type=\"button\" onClick={openCreate} className=\"gap-2\">\n <Plus className=\"h-4 w-4\" />\n Add Tenant\n </Button>\n }\n />\n )}\n </div>\n </div>\n\n {/* Maintenance Requests — list + resolve */}\n <div\n id=\"rental-maintenance\"\n className=\"scroll-mt-6 rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-sm\"\n >\n <h3 className=\"mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <Wrench className=\"h-5 w-5\" />\n Maintenance Requests\n </h3>\n {maintenanceRequests.length > 0 ? (\n <>\n <ul className=\"space-y-3\">\n {maintenanceRequests.map((request) => (\n <li\n key={request.id}\n className=\"flex flex-col gap-3 rounded-lg border border-border-subtle p-4 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium text-text-primary\">{request.title}</p>\n <StatusBadge\n label={request.status.replace('_', ' ')}\n variant={getMaintenanceVariant(request.status)}\n />\n <StatusBadge label={request.priority} variant={getPriorityVariant(request.priority)} />\n </div>\n <p className=\"mt-1 text-xs capitalize text-text-secondary\">\n {request.category}\n {request.description ? ` · ${request.description}` : ''}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">Raised {formatDate(request.createdAt)}</p>\n </div>\n {request.status !== 'resolved' ? (\n <Button type=\"button\" size=\"sm\" onClick={() => openResolve(request)} className=\"shrink-0 gap-1.5\">\n <CheckCircle className=\"h-3.5 w-3.5\" />\n Resolve\n </Button>\n ) : (\n <span className=\"shrink-0 text-xs text-text-secondary\">\n {request.resolvedAt ? `Resolved ${formatDate(request.resolvedAt)}` : 'Resolved'}\n </span>\n )}\n </li>\n ))}\n </ul>\n <div className=\"mt-4\">\n <Pagination\n page={maintListPagination.page}\n pageSize={maintListPagination.pageSize}\n hasNextPage={maintenanceRequests.length >= maintListPagination.pageSize}\n hasPreviousPage={maintListPagination.page > 1}\n onPageChange={maintListPagination.setPage}\n onPageSizeChange={maintListPagination.setPageSize}\n />\n </div>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Wrench className=\"h-10 w-10\" />}\n title=\"No maintenance requests\"\n description={\n maintListLoading\n ? 'Loading maintenance requests…'\n : 'Repairs raised against your units will appear here so you can track and resolve them.'\n }\n className=\"border-0 bg-transparent p-4\"\n />\n )}\n </div>\n\n {/* Add Tenant / Rental Unit dialog */}\n <ResponsiveDialog open={createOpen} onOpenChange={setCreateOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <form onSubmit={handleCreate}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add rental unit</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Register a unit and its tenant to start tracking rent and lease dates.\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\">Property *</label>\n <input\n type=\"text\"\n required\n placeholder=\"e.g. Maple Court\"\n value={propertyTitle}\n onChange={(e) => setPropertyTitle(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\">Unit number *</label>\n <input\n type=\"text\"\n required\n placeholder=\"e.g. 4B\"\n value={unitNumber}\n onChange={(e) => setUnitNumber(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\">Tenant name *</label>\n <input\n type=\"text\"\n required\n placeholder=\"Full name\"\n value={tenantName}\n onChange={(e) => setTenantName(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\">Tenant email *</label>\n <input\n type=\"email\"\n required\n placeholder=\"name@example.com\"\n value={tenantEmail}\n onChange={(e) => setTenantEmail(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\">Tenant phone</label>\n <input\n type=\"tel\"\n placeholder=\"Optional\"\n value={tenantPhone}\n onChange={(e) => setTenantPhone(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\">Monthly rent *</label>\n <input\n type=\"number\"\n required\n min={0}\n step=\"0.01\"\n placeholder=\"0.00\"\n value={monthlyRent}\n onChange={(e) => setMonthlyRent(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\">Lease start</label>\n <input\n type=\"date\"\n value={leaseStart}\n onChange={(e) => setLeaseStart(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\">Lease end</label>\n <input\n type=\"date\"\n value={leaseEnd}\n onChange={(e) => setLeaseEnd(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Status</label>\n <select\n value={status}\n onChange={(e) => setStatus(e.target.value as RentalStatus)}\n className={inputClass}\n >\n <option value=\"occupied\">Occupied</option>\n <option value=\"vacant\">Vacant</option>\n <option value=\"notice_period\">Notice period</option>\n <option value=\"maintenance\">Maintenance</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Payment</label>\n <select\n value={paymentStatus}\n onChange={(e) => setPaymentStatus(e.target.value as PaymentStatus)}\n className={inputClass}\n >\n <option value=\"paid\">Paid</option>\n <option value=\"pending\">Pending</option>\n <option value=\"overdue\">Overdue</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Deposit</label>\n <input\n type=\"number\"\n min={0}\n step=\"0.01\"\n placeholder=\"Optional\"\n value={securityDeposit}\n onChange={(e) => setSecurityDeposit(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setCreateOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={creating}>\n {creating ? 'Saving…' : 'Add unit'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Maintenance request dialog */}\n <ResponsiveDialog open={maintOpen} onOpenChange={setMaintOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleMaintenance}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Log maintenance request</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {maintUnit\n ? `Raise a repair for ${maintUnit.propertyTitle}, unit ${maintUnit.unitNumber}.`\n : 'Raise a repair for this unit.'}\n </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 placeholder=\"e.g. Leaking kitchen tap\"\n value={maintTitle}\n onChange={(e) => setMaintTitle(e.target.value)}\n className={inputClass}\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\">Category</label>\n <select\n value={maintCategory}\n onChange={(e) => setMaintCategory(e.target.value)}\n className={inputClass}\n >\n <option value=\"plumbing\">Plumbing</option>\n <option value=\"electrical\">Electrical</option>\n <option value=\"appliance\">Appliance</option>\n <option value=\"structural\">Structural</option>\n <option value=\"other\">Other</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Priority</label>\n <select\n value={maintPriority}\n onChange={(e) => setMaintPriority(e.target.value as 'low' | 'medium' | 'high')}\n className={inputClass}\n >\n <option value=\"low\">Low</option>\n <option value=\"medium\">Medium</option>\n <option value=\"high\">High</option>\n </select>\n </div>\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 placeholder=\"Optional — add context for the technician\"\n value={maintDescription}\n onChange={(e) => setMaintDescription(e.target.value)}\n className={textareaClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setMaintOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={submittingMaint}>\n {submittingMaint ? 'Submitting…' : 'Log request'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Resolve maintenance request dialog */}\n <ResponsiveDialog open={resolveOpen} onOpenChange={setResolveOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleResolve}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Resolve maintenance request</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {resolveTarget ? `Mark \"${resolveTarget.title}\" as resolved.` : 'Mark this request as resolved.'}\n </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\">Resolution notes</label>\n <textarea\n rows={3}\n placeholder=\"Optional — describe the fix or outcome\"\n value={resolutionNotes}\n onChange={(e) => setResolutionNotes(e.target.value)}\n className={textareaClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setResolveOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={resolving}>\n {resolving ? 'Resolving…' : 'Mark resolved'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Review rental application dialog */}\n <ResponsiveDialog open={reviewOpen} onOpenChange={setReviewOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleReview}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {reviewDecision === 'approved' ? 'Approve application' : 'Reject application'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {reviewTarget\n ? `${reviewTarget.applicantName} — ${\n reviewTarget.rentalUnit\n ? `${reviewTarget.rentalUnit.propertyTitle}, unit ${reviewTarget.rentalUnit.unitNumber}`\n : 'unit unavailable'\n }`\n : 'Review this rental application.'}\n </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\">Decision</label>\n <select\n value={reviewDecision}\n onChange={(e) => setReviewDecision(e.target.value as 'approved' | 'rejected')}\n className={inputClass}\n >\n <option value=\"approved\">Approve</option>\n <option value=\"rejected\">Reject</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Review notes</label>\n <textarea\n rows={3}\n placeholder=\"Optional — share the reason for your decision\"\n value={reviewNotes}\n onChange={(e) => setReviewNotes(e.target.value)}\n className={textareaClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setReviewOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={reviewing}>\n {reviewing ? 'Saving…' : reviewDecision === 'approved' ? 'Approve' : 'Reject'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"RentalManagementPage.js","names":[],"sources":["../../../../src/housingvista/pages/rental/RentalManagementPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect, type FormEvent } from 'react';\nimport {\n Home,\n Users,\n DollarSign,\n TrendingUp,\n Plus,\n FileText,\n CheckCircle,\n XCircle,\n AlertCircle,\n Clock,\n Wrench,\n} from 'lucide-react';\nimport {\n Button,\n EmphasisPanel,\n NextSteps,\n Pagination,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts';\nimport { PageLayout } from '../../components';\nimport { StatCard } from '../../components';\nimport { ChartCard } from '../../components';\nimport { DataTable, type Column } from '../../components';\nimport { StatusBadge } from '../../components';\nimport { FilterBar } from '../../components';\nimport { EmptyState } from '../../components';\nimport {\n useRentalUnits,\n useCreateRentalUnit,\n useCreateMaintenanceRequest,\n useMaintenanceRequests,\n useResolveMaintenanceRequest,\n useRentalApplications,\n useReviewRentalApplication,\n} from '../../hooks';\nimport type { MaintenanceRequestRow, RentalApplicationRow } from '../../hooks';\nimport { useServerPagination } from '../../hooks/useServerPagination';\nimport { formatCurrency, formatDate } from '../../utils/helpers';\nimport { notify } from '../../lib/toast';\nimport type { RentalUnit } from '../../types';\nimport { useTrackPageView } from '../../hooks/useHousingVistaAnalytics';\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// Payment-status colours: success / warning / error semantic status tokens.\nconst PAID_COLOR = 'var(--color-status-success-text)';\nconst PENDING_COLOR = 'var(--color-status-warning-text)';\nconst OVERDUE_COLOR = 'var(--color-status-error-text)';\nconst rentTooltipStyle: React.CSSProperties = {\n background: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-subtle)',\n borderRadius: 10,\n fontSize: 12,\n boxShadow: '0 8px 24px rgb(0 0 0 / 0.12)',\n};\nconst textareaClass =\n '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\ntype RentalStatus = 'occupied' | 'vacant' | 'notice_period' | 'maintenance';\ntype PaymentStatus = 'paid' | 'pending' | 'overdue';\n\nfunction toIso(value: string): string {\n return value ? new Date(value).toISOString() : '';\n}\n\nfunction getStatusVariant(status: RentalUnit['status']): 'success' | 'warning' | 'error' | 'info' | 'muted' {\n switch (status) {\n case 'occupied':\n return 'success';\n case 'vacant':\n return 'warning';\n case 'notice_period':\n return 'info';\n case 'maintenance':\n return 'error';\n default:\n return 'muted';\n }\n}\n\nfunction getPaymentVariant(status: RentalUnit['paymentStatus']): 'success' | 'warning' | 'error' | 'muted' {\n switch (status) {\n case 'paid':\n return 'success';\n case 'pending':\n return 'warning';\n case 'overdue':\n return 'error';\n default:\n return 'muted';\n }\n}\n\nfunction getApplicationVariant(\n status: RentalApplicationRow['status']\n): 'success' | 'warning' | 'error' | 'info' | 'muted' {\n switch (status) {\n case 'approved':\n return 'success';\n case 'rejected':\n return 'error';\n case 'screening':\n return 'warning';\n case 'submitted':\n return 'info';\n default:\n return 'muted';\n }\n}\n\nfunction getMaintenanceVariant(status: MaintenanceRequestRow['status']): 'success' | 'warning' | 'info' | 'muted' {\n switch (status) {\n case 'resolved':\n return 'success';\n case 'in_progress':\n return 'info';\n case 'open':\n return 'warning';\n default:\n return 'muted';\n }\n}\n\nfunction getPriorityVariant(priority: MaintenanceRequestRow['priority']): 'error' | 'warning' | 'muted' {\n switch (priority) {\n case 'high':\n return 'error';\n case 'medium':\n return 'warning';\n default:\n return 'muted';\n }\n}\n\nexport function RentalManagementPage() {\n useTrackPageView('housingvista.rental.viewed');\n const pagination = useServerPagination(10);\n const [search, setSearch] = useState('');\n const [debouncedSearch, setDebouncedSearch] = useState('');\n\n // Debounce the search box into the server filter (300ms).\n useEffect(() => {\n const handle = setTimeout(() => setDebouncedSearch(search), 300);\n return () => clearTimeout(handle);\n }, [search]);\n\n const { data: rentalUnits, loading } = useRentalUnits({\n filter: { search: debouncedSearch.trim() || undefined },\n pagination: pagination.pagination,\n });\n\n const handleSearchChange = (value: string) => {\n setSearch(value);\n pagination.setPage(1);\n };\n\n const { createRentalUnit, loading: creating } = useCreateRentalUnit();\n const { createMaintenanceRequest, loading: submittingMaint } = useCreateMaintenanceRequest();\n\n // ---- Maintenance requests (list + resolve) ----\n const maintListPagination = useServerPagination(5);\n const {\n data: maintenanceRequests,\n loading: maintListLoading,\n refetch: refetchMaintenance,\n } = useMaintenanceRequests({ pagination: maintListPagination.pagination });\n const { resolveMaintenanceRequest, loading: resolving } = useResolveMaintenanceRequest();\n\n const [resolveOpen, setResolveOpen] = useState(false);\n const [resolveTarget, setResolveTarget] = useState<MaintenanceRequestRow | null>(null);\n const [resolutionNotes, setResolutionNotes] = useState('');\n\n // ---- Rental applications (landlord review surface) ----\n const appPagination = useServerPagination(5);\n const [appStatus, setAppStatus] = useState<'all' | 'submitted' | 'screening' | 'approved' | 'rejected'>('all');\n const { data: applications, loading: applicationsLoading } = useRentalApplications({\n filter: { status: appStatus === 'all' ? undefined : appStatus },\n pagination: appPagination.pagination,\n });\n const { reviewRentalApplication, loading: reviewing } = useReviewRentalApplication();\n\n const [reviewOpen, setReviewOpen] = useState(false);\n const [reviewTarget, setReviewTarget] = useState<RentalApplicationRow | null>(null);\n const [reviewDecision, setReviewDecision] = useState<'approved' | 'rejected'>('approved');\n const [reviewNotes, setReviewNotes] = useState('');\n\n // Add-tenant dialog state\n const [createOpen, setCreateOpen] = useState(false);\n const [propertyTitle, setPropertyTitle] = useState('');\n const [unitNumber, setUnitNumber] = useState('');\n const [tenantName, setTenantName] = useState('');\n const [tenantEmail, setTenantEmail] = useState('');\n const [tenantPhone, setTenantPhone] = useState('');\n const [monthlyRent, setMonthlyRent] = useState('');\n const [leaseStart, setLeaseStart] = useState('');\n const [leaseEnd, setLeaseEnd] = useState('');\n const [status, setStatus] = useState<RentalStatus>('occupied');\n const [paymentStatus, setPaymentStatus] = useState<PaymentStatus>('pending');\n const [securityDeposit, setSecurityDeposit] = useState('');\n\n // Maintenance dialog state\n const [maintOpen, setMaintOpen] = useState(false);\n const [maintUnit, setMaintUnit] = useState<RentalUnit | null>(null);\n const [maintTitle, setMaintTitle] = useState('');\n const [maintDescription, setMaintDescription] = useState('');\n const [maintCategory, setMaintCategory] = useState('plumbing');\n const [maintPriority, setMaintPriority] = useState<'low' | 'medium' | 'high'>('medium');\n\n const resetCreateForm = () => {\n setPropertyTitle('');\n setUnitNumber('');\n setTenantName('');\n setTenantEmail('');\n setTenantPhone('');\n setMonthlyRent('');\n setLeaseStart('');\n setLeaseEnd('');\n setStatus('occupied');\n setPaymentStatus('pending');\n setSecurityDeposit('');\n };\n\n const openCreate = () => {\n resetCreateForm();\n setCreateOpen(true);\n };\n\n const handleCreate = async (e: FormEvent) => {\n e.preventDefault();\n const rent = Number(monthlyRent);\n if (!propertyTitle.trim() || !unitNumber.trim() || !tenantName.trim() || !tenantEmail.trim()) {\n notify.warning('Missing details', 'Property, unit, tenant name and email are required.');\n return;\n }\n if (!Number.isFinite(rent) || rent <= 0) {\n notify.warning('Enter a valid monthly rent');\n return;\n }\n const deposit = securityDeposit.trim() ? Number(securityDeposit) : undefined;\n try {\n await createRentalUnit({\n propertyTitle: propertyTitle.trim(),\n unitNumber: unitNumber.trim(),\n tenantName: tenantName.trim(),\n tenantEmail: tenantEmail.trim(),\n tenantPhone: tenantPhone.trim() || undefined,\n monthlyRent: rent,\n leaseStart: toIso(leaseStart),\n leaseEnd: toIso(leaseEnd),\n status,\n paymentStatus,\n securityDeposit: deposit !== undefined && Number.isFinite(deposit) ? deposit : undefined,\n });\n notify.success('Rental unit added', `${tenantName.trim()} added to ${propertyTitle.trim()}.`);\n setCreateOpen(false);\n resetCreateForm();\n } catch (err) {\n notify.error('Could not add rental unit', (err as Error).message);\n }\n };\n\n const openMaintenance = (unit: RentalUnit) => {\n setMaintUnit(unit);\n setMaintTitle('');\n setMaintDescription('');\n setMaintCategory('plumbing');\n setMaintPriority('medium');\n setMaintOpen(true);\n };\n\n const handleMaintenance = async (e: FormEvent) => {\n e.preventDefault();\n if (!maintUnit) return;\n if (!maintTitle.trim()) {\n notify.warning('Add a short title for the request');\n return;\n }\n try {\n await createMaintenanceRequest({\n rentalUnitId: maintUnit.id,\n title: maintTitle.trim(),\n description: maintDescription.trim() || undefined,\n category: maintCategory,\n priority: maintPriority,\n });\n notify.success(\n 'Maintenance request logged',\n `Raised for ${maintUnit.propertyTitle}, unit ${maintUnit.unitNumber}.`\n );\n setMaintOpen(false);\n setMaintUnit(null);\n await refetchMaintenance();\n } catch (err) {\n notify.error('Could not log maintenance request', (err as Error).message);\n }\n };\n\n const openResolve = (request: MaintenanceRequestRow) => {\n setResolveTarget(request);\n setResolutionNotes('');\n setResolveOpen(true);\n };\n\n const handleResolve = async (e: FormEvent) => {\n e.preventDefault();\n if (!resolveTarget) return;\n try {\n await resolveMaintenanceRequest(resolveTarget.id, resolutionNotes.trim() || undefined);\n notify.success('Request resolved', `\"${resolveTarget.title}\" was marked resolved.`);\n setResolveOpen(false);\n setResolveTarget(null);\n } catch (err) {\n notify.error('Could not resolve request', (err as Error).message);\n }\n };\n\n const openReview = (application: RentalApplicationRow, decision: 'approved' | 'rejected') => {\n setReviewTarget(application);\n setReviewDecision(decision);\n setReviewNotes('');\n setReviewOpen(true);\n };\n\n const handleReview = async (e: FormEvent) => {\n e.preventDefault();\n if (!reviewTarget) return;\n try {\n await reviewRentalApplication(reviewTarget.id, {\n decision: reviewDecision,\n reviewNotes: reviewNotes.trim() || undefined,\n });\n notify.success(\n reviewDecision === 'approved' ? 'Application approved' : 'Application rejected',\n `${reviewTarget.applicantName}'s application was ${reviewDecision}.`\n );\n setReviewOpen(false);\n setReviewTarget(null);\n } catch (err) {\n notify.error('Could not update application', (err as Error).message);\n }\n };\n\n const stats = useMemo(() => {\n const totalUnits = rentalUnits.length;\n const occupied = rentalUnits.filter((u) => u.status === 'occupied').length;\n const vacant = rentalUnits.filter((u) => u.status === 'vacant').length;\n const monthlyIncome = rentalUnits\n .filter((u) => u.status === 'occupied' || u.status === 'notice_period')\n .reduce((sum, u) => sum + u.monthlyRent, 0);\n return { totalUnits, occupied, vacant, monthlyIncome };\n }, [rentalUnits]);\n\n const rentCollectionStats = useMemo(() => {\n const paid = rentalUnits.filter((u) => u.paymentStatus === 'paid').length;\n const pending = rentalUnits.filter((u) => u.paymentStatus === 'pending').length;\n const overdue = rentalUnits.filter((u) => u.paymentStatus === 'overdue').length;\n const collectionRate = rentalUnits.length > 0 ? (paid / rentalUnits.length) * 100 : 0;\n const collectedRent = rentalUnits\n .filter((u) => u.paymentStatus === 'paid')\n .reduce((sum, u) => sum + u.monthlyRent, 0);\n const outstandingRent = rentalUnits\n .filter((u) => u.paymentStatus === 'pending' || u.paymentStatus === 'overdue')\n .reduce((sum, u) => sum + u.monthlyRent, 0);\n return { paid, pending, overdue, collectionRate, collectedRent, outstandingRent };\n }, [rentalUnits]);\n\n // Real payment-status breakdown for the collection donut (page-scoped, like the tiles).\n const rentCollectionChart = useMemo(\n () =>\n [\n { name: 'Paid', value: rentCollectionStats.paid, color: PAID_COLOR },\n { name: 'Pending', value: rentCollectionStats.pending, color: PENDING_COLOR },\n { name: 'Overdue', value: rentCollectionStats.overdue, color: OVERDUE_COLOR },\n ].filter((slice) => slice.value > 0),\n [rentCollectionStats]\n );\n\n const tenantColumns: Column<RentalUnit>[] = [\n {\n key: 'unitNumber',\n header: 'Unit',\n render: (item) => (\n <div>\n <div className=\"font-medium text-text-primary\">{item.propertyTitle}</div>\n <div className=\"text-xs text-text-secondary\">Unit {item.unitNumber}</div>\n </div>\n ),\n },\n {\n key: 'tenantName',\n header: 'Tenant',\n render: (item) =>\n item.tenantName ? (\n <div>\n <div className=\"font-medium text-text-primary\">{item.tenantName}</div>\n <div className=\"text-xs text-text-secondary\">{item.tenantEmail}</div>\n </div>\n ) : (\n <span className=\"text-text-secondary\">-</span>\n ),\n },\n {\n key: 'leaseStart',\n header: 'Lease Start',\n render: (item) =>\n item.leaseStart ? (\n <span className=\"text-sm text-text-primary\">{formatDate(item.leaseStart)}</span>\n ) : (\n <span className=\"text-text-secondary\">-</span>\n ),\n },\n {\n key: 'leaseEnd',\n header: 'Lease End',\n render: (item) =>\n item.leaseEnd ? (\n <span className=\"text-sm text-text-primary\">{formatDate(item.leaseEnd)}</span>\n ) : (\n <span className=\"text-text-secondary\">-</span>\n ),\n },\n {\n key: 'monthlyRent',\n header: 'Rent',\n render: (item) => <span className=\"font-medium text-text-primary\">{formatCurrency(item.monthlyRent)}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n render: (item) => (\n <div className=\"flex flex-col gap-1\">\n <StatusBadge label={item.status.replace('_', ' ')} variant={getStatusVariant(item.status)} />\n <StatusBadge label={item.paymentStatus} variant={getPaymentVariant(item.paymentStatus)} />\n </div>\n ),\n },\n {\n key: 'actions',\n header: '',\n render: (item) => (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => openMaintenance(item)} className=\"gap-1.5\">\n <Wrench className=\"h-3.5 w-3.5\" />\n Maintenance\n </Button>\n ),\n },\n ];\n\n return (\n <PageLayout\n title=\"Rental Management\"\n description=\"Comprehensive property and tenant management dashboard\"\n purpose=\"Run your rentals as a business — track which units are occupied or vacant, who your tenants are, what rent is collected versus outstanding, and what needs action. Use it to chase late payments, fill vacancies, and keep leases current.\"\n actions={\n <Button type=\"button\" onClick={openCreate} className=\"gap-2\">\n <Plus className=\"h-4 w-4\" />\n Add Tenant\n </Button>\n }\n >\n <NextSteps\n storageKey=\"housingvista-rental\"\n steps={[\n {\n id: 'collection',\n label: 'Check rent collection',\n description: `${rentCollectionStats.overdue} overdue, ${rentCollectionStats.pending} pending — review who still owes.`,\n href: '#rental-collection',\n },\n {\n id: 'tenants',\n label: 'Find a tenant',\n description: 'Search the tenant directory to review leases and contacts.',\n href: '#rental-tenants',\n },\n ]}\n />\n\n {/* Stats Row — primary insight zone (one EmphasisPanel per page) */}\n <EmphasisPanel className=\"p-4\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard label=\"Total Units\" value={stats.totalUnits} icon={<Home className=\"h-4 w-4\" />} />\n <StatCard label=\"Occupied\" value={stats.occupied} icon={<Users className=\"h-4 w-4\" />} />\n <StatCard label=\"Vacant\" value={stats.vacant} icon={<Home className=\"h-4 w-4\" />} />\n <StatCard\n label=\"Monthly Income\"\n value={stats.monthlyIncome}\n prefix=\"$\"\n icon={<DollarSign className=\"h-4 w-4\" />}\n />\n </div>\n </EmphasisPanel>\n\n {/* Rent Collection Section — status donut + real collection tiles */}\n <div id=\"rental-collection\" className=\"scroll-mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <ChartCard title=\"Rent Collection\" description=\"This page's units by payment status\" className=\"lg:col-span-1\">\n {rentCollectionChart.length > 0 ? (\n <div className=\"relative h-52 w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <PieChart>\n <Pie\n data={rentCollectionChart}\n dataKey=\"value\"\n nameKey=\"name\"\n innerRadius={54}\n outerRadius={80}\n paddingAngle={2}\n stroke=\"var(--color-bg-surface)\"\n strokeWidth={2}\n >\n {rentCollectionChart.map((slice) => (\n <Cell key={slice.name} fill={slice.color} />\n ))}\n </Pie>\n <Tooltip\n contentStyle={rentTooltipStyle}\n formatter={(value: number, name) => [`${value} ${value === 1 ? 'unit' : 'units'}`, name]}\n />\n </PieChart>\n </ResponsiveContainer>\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center\">\n <span className=\"text-2xl font-bold text-text-primary\">\n {rentCollectionStats.collectionRate.toFixed(0)}%\n </span>\n <span className=\"text-xs text-text-secondary\">collected</span>\n </div>\n </div>\n ) : (\n <div className=\"flex h-52 items-center justify-center text-sm text-text-secondary\">\n No payment data on this page yet.\n </div>\n )}\n </ChartCard>\n\n <div className=\"lg:col-span-2\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"flex items-center gap-3 rounded-lg bg-status-success-bg-subtle p-4\">\n <CheckCircle className=\"h-5 w-5 text-status-success-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Paid</p>\n <p className=\"text-xl font-bold text-status-success-text\">{rentCollectionStats.paid}</p>\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(rentCollectionStats.collectedRent)} collected\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-lg bg-status-warning-bg-subtle p-4\">\n <Clock className=\"h-5 w-5 text-status-warning-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Pending</p>\n <p className=\"text-xl font-bold text-status-warning-text\">{rentCollectionStats.pending}</p>\n <p className=\"text-xs text-text-secondary\">awaiting payment</p>\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-lg bg-status-error-bg-subtle p-4\">\n <AlertCircle className=\"h-5 w-5 text-status-error-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Overdue</p>\n <p className=\"text-xl font-bold text-status-error-text\">{rentCollectionStats.overdue}</p>\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(rentCollectionStats.outstandingRent)} outstanding\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-lg bg-status-info-bg-subtle p-4\">\n <TrendingUp className=\"h-5 w-5 text-status-info-text\" />\n <div>\n <p className=\"text-sm text-text-secondary\">Collection Rate</p>\n <p className=\"text-xl font-bold text-status-info-text\">\n {rentCollectionStats.collectionRate.toFixed(0)}%\n </p>\n <p className=\"text-xs text-text-secondary\">of units paid</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {/* Rental Applications — landlord review surface */}\n <div\n id=\"rental-applications\"\n className=\"scroll-mt-6 rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-sm\"\n >\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-3\">\n <h3 className=\"flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <FileText className=\"h-5 w-5\" />\n Rental Applications\n </h3>\n <div className=\"flex flex-wrap items-center gap-2\">\n {(['all', 'submitted', 'screening', 'approved', 'rejected'] as const).map((value) => (\n <button\n key={value}\n type=\"button\"\n onClick={() => {\n setAppStatus(value);\n appPagination.setPage(1);\n }}\n className={`rounded-md px-3 py-1.5 text-xs font-medium capitalize transition-colors ${\n appStatus === value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n }`}\n >\n {value}\n </button>\n ))}\n </div>\n </div>\n {applications.length > 0 ? (\n <>\n <ul className=\"space-y-3\">\n {applications.map((application) => (\n <li\n key={application.id}\n className=\"flex flex-col gap-3 rounded-lg border border-border-subtle p-4 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium text-text-primary\">{application.applicantName}</p>\n <StatusBadge label={application.status} variant={getApplicationVariant(application.status)} />\n </div>\n <p className=\"truncate text-xs text-text-secondary\">{application.applicantEmail}</p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {application.rentalUnit\n ? `${application.rentalUnit.propertyTitle}, unit ${application.rentalUnit.unitNumber}`\n : 'Unit unavailable'}\n {application.monthlyIncome != null\n ? ` · Income ${formatCurrency(application.monthlyIncome)}`\n : ''}\n {application.moveInDate ? ` · Move-in ${formatDate(application.moveInDate)}` : ''}\n </p>\n </div>\n {application.status === 'submitted' || application.status === 'screening' ? (\n <div className=\"flex shrink-0 items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => openReview(application, 'rejected')}\n className=\"gap-1.5\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Reject\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => openReview(application, 'approved')}\n className=\"gap-1.5\"\n >\n <CheckCircle className=\"h-3.5 w-3.5\" />\n Approve\n </Button>\n </div>\n ) : (\n <span className=\"shrink-0 text-xs text-text-secondary\">\n {application.reviewedAt ? `Reviewed ${formatDate(application.reviewedAt)}` : 'Reviewed'}\n </span>\n )}\n </li>\n ))}\n </ul>\n <div className=\"mt-4\">\n <Pagination\n page={appPagination.page}\n pageSize={appPagination.pageSize}\n hasNextPage={applications.length >= appPagination.pageSize}\n hasPreviousPage={appPagination.page > 1}\n onPageChange={appPagination.setPage}\n onPageSizeChange={appPagination.setPageSize}\n />\n </div>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<FileText className=\"h-10 w-10\" />}\n title=\"No applications\"\n description={\n applicationsLoading\n ? 'Loading applications…'\n : 'Rental applications from prospective tenants will appear here for review.'\n }\n className=\"border-0 bg-transparent p-4\"\n />\n )}\n </div>\n\n {/* Tenant List */}\n <div id=\"rental-tenants\" className=\"scroll-mt-6\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Tenant Directory</h2>\n <FilterBar\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder=\"Search units, tenants...\"\n />\n <div className=\"mt-4\">\n {rentalUnits.length > 0 ? (\n <DataTable\n columns={tenantColumns}\n data={rentalUnits}\n keyField=\"id\"\n pageSize={10}\n serverPagination={{\n page: pagination.page,\n pageSize: pagination.pageSize,\n hasNextPage: rentalUnits.length >= pagination.pageSize,\n loading,\n onPageChange: pagination.setPage,\n onPageSizeChange: pagination.setPageSize,\n }}\n />\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n icon={<Users className=\"h-12 w-12\" />}\n title=\"No rental units found\"\n description=\"Try adjusting your search criteria or add a new tenant.\"\n action={\n <Button type=\"button\" onClick={openCreate} className=\"gap-2\">\n <Plus className=\"h-4 w-4\" />\n Add Tenant\n </Button>\n }\n />\n )}\n </div>\n </div>\n\n {/* Maintenance Requests — list + resolve */}\n <div\n id=\"rental-maintenance\"\n className=\"scroll-mt-6 rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-sm\"\n >\n <h3 className=\"mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <Wrench className=\"h-5 w-5\" />\n Maintenance Requests\n </h3>\n {maintenanceRequests.length > 0 ? (\n <>\n <ul className=\"space-y-3\">\n {maintenanceRequests.map((request) => (\n <li\n key={request.id}\n className=\"flex flex-col gap-3 rounded-lg border border-border-subtle p-4 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium text-text-primary\">{request.title}</p>\n <StatusBadge\n label={request.status.replace('_', ' ')}\n variant={getMaintenanceVariant(request.status)}\n />\n <StatusBadge label={request.priority} variant={getPriorityVariant(request.priority)} />\n </div>\n <p className=\"mt-1 text-xs capitalize text-text-secondary\">\n {request.category}\n {request.description ? ` · ${request.description}` : ''}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">Raised {formatDate(request.createdAt)}</p>\n </div>\n {request.status !== 'resolved' ? (\n <Button type=\"button\" size=\"sm\" onClick={() => openResolve(request)} className=\"shrink-0 gap-1.5\">\n <CheckCircle className=\"h-3.5 w-3.5\" />\n Resolve\n </Button>\n ) : (\n <span className=\"shrink-0 text-xs text-text-secondary\">\n {request.resolvedAt ? `Resolved ${formatDate(request.resolvedAt)}` : 'Resolved'}\n </span>\n )}\n </li>\n ))}\n </ul>\n <div className=\"mt-4\">\n <Pagination\n page={maintListPagination.page}\n pageSize={maintListPagination.pageSize}\n hasNextPage={maintenanceRequests.length >= maintListPagination.pageSize}\n hasPreviousPage={maintListPagination.page > 1}\n onPageChange={maintListPagination.setPage}\n onPageSizeChange={maintListPagination.setPageSize}\n />\n </div>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Wrench className=\"h-10 w-10\" />}\n title=\"No maintenance requests\"\n description={\n maintListLoading\n ? 'Loading maintenance requests…'\n : 'Repairs raised against your units will appear here so you can track and resolve them.'\n }\n className=\"border-0 bg-transparent p-4\"\n />\n )}\n </div>\n\n {/* Add Tenant / Rental Unit dialog */}\n <ResponsiveDialog open={createOpen} onOpenChange={setCreateOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <form onSubmit={handleCreate}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add rental unit</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Register a unit and its tenant to start tracking rent and lease dates.\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\">Property *</label>\n <input\n type=\"text\"\n required\n placeholder=\"e.g. Maple Court\"\n value={propertyTitle}\n onChange={(e) => setPropertyTitle(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\">Unit number *</label>\n <input\n type=\"text\"\n required\n placeholder=\"e.g. 4B\"\n value={unitNumber}\n onChange={(e) => setUnitNumber(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\">Tenant name *</label>\n <input\n type=\"text\"\n required\n placeholder=\"Full name\"\n value={tenantName}\n onChange={(e) => setTenantName(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\">Tenant email *</label>\n <input\n type=\"email\"\n required\n placeholder=\"name@example.com\"\n value={tenantEmail}\n onChange={(e) => setTenantEmail(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\">Tenant phone</label>\n <input\n type=\"tel\"\n placeholder=\"Optional\"\n value={tenantPhone}\n onChange={(e) => setTenantPhone(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\">Monthly rent *</label>\n <input\n type=\"number\"\n required\n min={0}\n step=\"0.01\"\n placeholder=\"0.00\"\n value={monthlyRent}\n onChange={(e) => setMonthlyRent(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\">Lease start</label>\n <input\n type=\"date\"\n value={leaseStart}\n onChange={(e) => setLeaseStart(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\">Lease end</label>\n <input\n type=\"date\"\n value={leaseEnd}\n onChange={(e) => setLeaseEnd(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Status</label>\n <select\n value={status}\n onChange={(e) => setStatus(e.target.value as RentalStatus)}\n className={inputClass}\n >\n <option value=\"occupied\">Occupied</option>\n <option value=\"vacant\">Vacant</option>\n <option value=\"notice_period\">Notice period</option>\n <option value=\"maintenance\">Maintenance</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Payment</label>\n <select\n value={paymentStatus}\n onChange={(e) => setPaymentStatus(e.target.value as PaymentStatus)}\n className={inputClass}\n >\n <option value=\"paid\">Paid</option>\n <option value=\"pending\">Pending</option>\n <option value=\"overdue\">Overdue</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Deposit</label>\n <input\n type=\"number\"\n min={0}\n step=\"0.01\"\n placeholder=\"Optional\"\n value={securityDeposit}\n onChange={(e) => setSecurityDeposit(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setCreateOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={creating}>\n {creating ? 'Saving…' : 'Add unit'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Maintenance request dialog */}\n <ResponsiveDialog open={maintOpen} onOpenChange={setMaintOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleMaintenance}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Log maintenance request</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {maintUnit\n ? `Raise a repair for ${maintUnit.propertyTitle}, unit ${maintUnit.unitNumber}.`\n : 'Raise a repair for this unit.'}\n </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 placeholder=\"e.g. Leaking kitchen tap\"\n value={maintTitle}\n onChange={(e) => setMaintTitle(e.target.value)}\n className={inputClass}\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\">Category</label>\n <select\n value={maintCategory}\n onChange={(e) => setMaintCategory(e.target.value)}\n className={inputClass}\n >\n <option value=\"plumbing\">Plumbing</option>\n <option value=\"electrical\">Electrical</option>\n <option value=\"appliance\">Appliance</option>\n <option value=\"structural\">Structural</option>\n <option value=\"other\">Other</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Priority</label>\n <select\n value={maintPriority}\n onChange={(e) => setMaintPriority(e.target.value as 'low' | 'medium' | 'high')}\n className={inputClass}\n >\n <option value=\"low\">Low</option>\n <option value=\"medium\">Medium</option>\n <option value=\"high\">High</option>\n </select>\n </div>\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 placeholder=\"Optional — add context for the technician\"\n value={maintDescription}\n onChange={(e) => setMaintDescription(e.target.value)}\n className={textareaClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setMaintOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={submittingMaint}>\n {submittingMaint ? 'Submitting…' : 'Log request'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Resolve maintenance request dialog */}\n <ResponsiveDialog open={resolveOpen} onOpenChange={setResolveOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleResolve}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Resolve maintenance request</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {resolveTarget ? `Mark \"${resolveTarget.title}\" as resolved.` : 'Mark this request as resolved.'}\n </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\">Resolution notes</label>\n <textarea\n rows={3}\n placeholder=\"Optional — describe the fix or outcome\"\n value={resolutionNotes}\n onChange={(e) => setResolutionNotes(e.target.value)}\n className={textareaClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setResolveOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={resolving}>\n {resolving ? 'Resolving…' : 'Mark resolved'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Review rental application dialog */}\n <ResponsiveDialog open={reviewOpen} onOpenChange={setReviewOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleReview}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {reviewDecision === 'approved' ? 'Approve application' : 'Reject application'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {reviewTarget\n ? `${reviewTarget.applicantName} — ${\n reviewTarget.rentalUnit\n ? `${reviewTarget.rentalUnit.propertyTitle}, unit ${reviewTarget.rentalUnit.unitNumber}`\n : 'unit unavailable'\n }`\n : 'Review this rental application.'}\n </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\">Decision</label>\n <select\n value={reviewDecision}\n onChange={(e) => setReviewDecision(e.target.value as 'approved' | 'rejected')}\n className={inputClass}\n >\n <option value=\"approved\">Approve</option>\n <option value=\"rejected\">Reject</option>\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Review notes</label>\n <textarea\n rows={3}\n placeholder=\"Optional — share the reason for your decision\"\n value={reviewNotes}\n onChange={(e) => setReviewNotes(e.target.value)}\n className={textareaClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setReviewOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={reviewing}>\n {reviewing ? 'Saving…' : reviewDecision === 'approved' ? 'Approve' : 'Reject'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfilePage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/settings/ProfilePage.tsx"],"names":[],"mappings":"AAcA,wBAAgB,WAAW,gCAqG1B"}
1
+ {"version":3,"file":"ProfilePage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/settings/ProfilePage.tsx"],"names":[],"mappings":"AAeA,wBAAgB,WAAW,gCAsG1B"}
@@ -1,104 +1,106 @@
1
1
  import { useHousingVista as e } from "../../context/HousingVistaContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { useTrackPageView as n } from "../../hooks/useHousingVistaAnalytics.js";
3
4
  import "../../components/index.js";
4
- import { ExternalLink as n, Mail as r, User as i } from "lucide-react";
5
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
- import { EmphasisPanel as s } from "@burdenoff/fe-libs/ui";
5
+ import { ExternalLink as r, Mail as i, User as a } from "lucide-react";
6
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
+ import { EmphasisPanel as c } from "@burdenoff/fe-libs/ui";
7
8
  //#region src/housingvista/pages/settings/ProfilePage.tsx
8
- var c = "/auth/security";
9
- function l() {
10
- let { currentUser: l } = e(), u = l?.firstName ?? "", d = l?.lastName ?? "";
11
- if (!u && !d && l?.name) {
12
- let e = l.name.trim().split(/\s+/).filter(Boolean);
13
- u = e[0] ?? "", d = e.slice(1).join(" ");
9
+ var l = "/auth/security";
10
+ function u() {
11
+ n("housingvista.profile.viewed");
12
+ let { currentUser: u } = e(), d = u?.firstName ?? "", f = u?.lastName ?? "";
13
+ if (!d && !f && u?.name) {
14
+ let e = u.name.trim().split(/\s+/).filter(Boolean);
15
+ d = e[0] ?? "", f = e.slice(1).join(" ");
14
16
  }
15
- let f = l?.email ?? "", p = l?.avatar, m = l?.role, h = l?.name || `${u} ${d}`.trim() || f || "Your profile", g = `${u.charAt(0)}${d.charAt(0)}`.toUpperCase() || f.charAt(0).toUpperCase() || "?", _ = () => window.location.assign(c);
16
- return /* @__PURE__ */ o(t, {
17
+ let p = u?.email ?? "", m = u?.avatar, h = u?.role, g = u?.name || `${d} ${f}`.trim() || p || "Your profile", _ = `${d.charAt(0)}${f.charAt(0)}`.toUpperCase() || p.charAt(0).toUpperCase() || "?", v = () => window.location.assign(l);
18
+ return /* @__PURE__ */ s(t, {
17
19
  title: "My Profile",
18
20
  description: "Your personal information across HousingVista",
19
21
  purpose: "Your identity across HousingVista. This is how owners, agents, and service providers see you on your listings and deals. Your account details are managed by the platform — use “Manage your profile” to update them.",
20
- actions: /* @__PURE__ */ o("button", {
21
- onClick: _,
22
+ actions: /* @__PURE__ */ s("button", {
23
+ onClick: v,
22
24
  className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover",
23
- children: [/* @__PURE__ */ a(n, { className: "h-3.5 w-3.5" }), "Manage your profile"]
25
+ children: [/* @__PURE__ */ o(r, { className: "h-3.5 w-3.5" }), "Manage your profile"]
24
26
  }),
25
- children: [/* @__PURE__ */ a(s, {
27
+ children: [/* @__PURE__ */ o(c, {
26
28
  className: "p-6",
27
- children: /* @__PURE__ */ o("div", {
29
+ children: /* @__PURE__ */ s("div", {
28
30
  className: "flex flex-col items-center gap-4 sm:flex-row sm:items-start",
29
- children: [/* @__PURE__ */ a("div", {
31
+ children: [/* @__PURE__ */ o("div", {
30
32
  className: "flex h-24 w-24 items-center justify-center overflow-hidden rounded-full bg-bg-sunken text-2xl font-bold text-text-primary",
31
- children: p ? /* @__PURE__ */ a("img", {
32
- src: p,
33
- alt: h,
33
+ children: m ? /* @__PURE__ */ o("img", {
34
+ src: m,
35
+ alt: g,
34
36
  className: "h-full w-full object-cover"
35
- }) : g
36
- }), /* @__PURE__ */ o("div", {
37
+ }) : _
38
+ }), /* @__PURE__ */ s("div", {
37
39
  className: "flex-1 text-center sm:text-left",
38
40
  children: [
39
- /* @__PURE__ */ a("h2", {
41
+ /* @__PURE__ */ o("h2", {
40
42
  className: "text-xl font-semibold text-text-primary",
41
- children: h
43
+ children: g
42
44
  }),
43
- /* @__PURE__ */ a("div", {
45
+ /* @__PURE__ */ o("div", {
44
46
  className: "mt-1 flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-3",
45
- children: f && /* @__PURE__ */ o("span", {
47
+ children: p && /* @__PURE__ */ s("span", {
46
48
  className: "flex items-center justify-center gap-1 text-sm text-text-secondary sm:justify-start",
47
- children: [/* @__PURE__ */ a(r, { className: "h-3.5 w-3.5" }), f]
49
+ children: [/* @__PURE__ */ o(i, { className: "h-3.5 w-3.5" }), p]
48
50
  })
49
51
  }),
50
- m && /* @__PURE__ */ a("div", {
52
+ h && /* @__PURE__ */ o("div", {
51
53
  className: "mt-2",
52
- children: /* @__PURE__ */ o("span", {
54
+ children: /* @__PURE__ */ s("span", {
53
55
  className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-primary",
54
- children: [/* @__PURE__ */ a(i, { className: "h-3 w-3" }), m]
56
+ children: [/* @__PURE__ */ o(a, { className: "h-3 w-3" }), h]
55
57
  })
56
58
  })
57
59
  ]
58
60
  })]
59
61
  })
60
- }), /* @__PURE__ */ o("div", {
62
+ }), /* @__PURE__ */ s("div", {
61
63
  className: "rounded-lg border border-border-subtle bg-bg-surface p-6",
62
- children: [/* @__PURE__ */ o("div", {
64
+ children: [/* @__PURE__ */ s("div", {
63
65
  className: "mb-4 flex items-center justify-between gap-4",
64
- children: [/* @__PURE__ */ a("h3", {
66
+ children: [/* @__PURE__ */ o("h3", {
65
67
  className: "text-base font-semibold text-text-primary",
66
68
  children: "Personal Information"
67
- }), /* @__PURE__ */ o("button", {
68
- onClick: _,
69
+ }), /* @__PURE__ */ s("button", {
70
+ onClick: v,
69
71
  className: "inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken",
70
- children: [/* @__PURE__ */ a(n, { className: "h-3.5 w-3.5" }), "Manage your profile"]
72
+ children: [/* @__PURE__ */ o(r, { className: "h-3.5 w-3.5" }), "Manage your profile"]
71
73
  })]
72
- }), /* @__PURE__ */ o("dl", {
74
+ }), /* @__PURE__ */ s("dl", {
73
75
  className: "grid gap-5 sm:grid-cols-2",
74
76
  children: [
75
- /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("dt", {
77
+ /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("dt", {
76
78
  className: "mb-1 text-sm font-medium text-text-secondary",
77
79
  children: "First Name"
78
- }), /* @__PURE__ */ a("dd", {
80
+ }), /* @__PURE__ */ o("dd", {
79
81
  className: "text-sm text-text-primary",
80
- children: u || "—"
82
+ children: d || "—"
81
83
  })] }),
82
- /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("dt", {
84
+ /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("dt", {
83
85
  className: "mb-1 text-sm font-medium text-text-secondary",
84
86
  children: "Last Name"
85
- }), /* @__PURE__ */ a("dd", {
87
+ }), /* @__PURE__ */ o("dd", {
86
88
  className: "text-sm text-text-primary",
87
- children: d || "—"
89
+ children: f || "—"
88
90
  })] }),
89
- /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("dt", {
91
+ /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("dt", {
90
92
  className: "mb-1 text-sm font-medium text-text-secondary",
91
93
  children: "Email"
92
- }), /* @__PURE__ */ a("dd", {
94
+ }), /* @__PURE__ */ o("dd", {
93
95
  className: "text-sm text-text-primary",
94
- children: f || "—"
96
+ children: p || "—"
95
97
  })] }),
96
- m && /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("dt", {
98
+ h && /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("dt", {
97
99
  className: "mb-1 text-sm font-medium text-text-secondary",
98
100
  children: "Role"
99
- }), /* @__PURE__ */ a("dd", {
101
+ }), /* @__PURE__ */ o("dd", {
100
102
  className: "text-sm text-text-primary",
101
- children: m
103
+ children: h
102
104
  })] })
103
105
  ]
104
106
  })]
@@ -106,6 +108,6 @@ function l() {
106
108
  });
107
109
  }
108
110
  //#endregion
109
- export { l as ProfilePage };
111
+ export { u as ProfilePage };
110
112
 
111
113
  //# sourceMappingURL=ProfilePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfilePage.js","names":[],"sources":["../../../../src/housingvista/pages/settings/ProfilePage.tsx"],"sourcesContent":["import { User, Mail, ExternalLink } from 'lucide-react';\nimport { EmphasisPanel } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components';\nimport { useHousingVista } from '../../context/HousingVistaContext';\n\n/**\n * Read-only profile view. This MFE exposes no profile-update mutation — account\n * identity (name, email, avatar, photo, role) is owned by the platform app shell.\n * We render what the shell hands us via `currentUser` and link out to the shell\n * account settings to make any change, rather than presenting a Save button that\n * cannot persist.\n */\nconst SHELL_ACCOUNT_ROUTE = '/auth/security';\n\nexport function ProfilePage() {\n const { currentUser } = useHousingVista();\n\n let firstName = currentUser?.firstName ?? '';\n let lastName = currentUser?.lastName ?? '';\n if (!firstName && !lastName && currentUser?.name) {\n const parts = currentUser.name.trim().split(/\\s+/).filter(Boolean);\n firstName = parts[0] ?? '';\n lastName = parts.slice(1).join(' ');\n }\n\n const email = currentUser?.email ?? '';\n const avatar = currentUser?.avatar;\n const role = currentUser?.role;\n const displayName = currentUser?.name || `${firstName} ${lastName}`.trim() || email || 'Your profile';\n\n const initials = `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase() || email.charAt(0).toUpperCase() || '?';\n\n const manageProfile = () => window.location.assign(SHELL_ACCOUNT_ROUTE);\n\n return (\n <PageLayout\n title=\"My Profile\"\n description=\"Your personal information across HousingVista\"\n purpose=\"Your identity across HousingVista. This is how owners, agents, and service providers see you on your listings and deals. Your account details are managed by the platform — use “Manage your profile” to update them.\"\n actions={\n <button\n onClick={manageProfile}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n Manage your profile\n </button>\n }\n >\n {/* Profile Card — primary emphasis zone (one per page) */}\n <EmphasisPanel className=\"p-6\">\n <div className=\"flex flex-col items-center gap-4 sm:flex-row sm:items-start\">\n {/* Avatar */}\n <div className=\"flex h-24 w-24 items-center justify-center overflow-hidden rounded-full bg-bg-sunken text-2xl font-bold text-text-primary\">\n {avatar ? <img src={avatar} alt={displayName} className=\"h-full w-full object-cover\" /> : initials}\n </div>\n\n {/* Info */}\n <div className=\"flex-1 text-center sm:text-left\">\n <h2 className=\"text-xl font-semibold text-text-primary\">{displayName}</h2>\n <div className=\"mt-1 flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-3\">\n {email && (\n <span className=\"flex items-center justify-center gap-1 text-sm text-text-secondary sm:justify-start\">\n <Mail className=\"h-3.5 w-3.5\" />\n {email}\n </span>\n )}\n </div>\n {role && (\n <div className=\"mt-2\">\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-primary\">\n <User className=\"h-3 w-3\" />\n {role}\n </span>\n </div>\n )}\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Personal Information — read-only */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"mb-4 flex items-center justify-between gap-4\">\n <h3 className=\"text-base font-semibold text-text-primary\">Personal Information</h3>\n <button\n onClick={manageProfile}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n Manage your profile\n </button>\n </div>\n <dl className=\"grid gap-5 sm:grid-cols-2\">\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">First Name</dt>\n <dd className=\"text-sm text-text-primary\">{firstName || '—'}</dd>\n </div>\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">Last Name</dt>\n <dd className=\"text-sm text-text-primary\">{lastName || '—'}</dd>\n </div>\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">Email</dt>\n <dd className=\"text-sm text-text-primary\">{email || '—'}</dd>\n </div>\n {role && (\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">Role</dt>\n <dd className=\"text-sm text-text-primary\">{role}</dd>\n </div>\n )}\n </dl>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;AAYA,IAAM,IAAsB;AAE5B,SAAgB,IAAc;CAC5B,IAAM,EAAE,mBAAgB,GAAiB,EAErC,IAAY,GAAa,aAAa,IACtC,IAAW,GAAa,YAAY;AACxC,KAAI,CAAC,KAAa,CAAC,KAAY,GAAa,MAAM;EAChD,IAAM,IAAQ,EAAY,KAAK,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,QAAQ;AAElE,EADA,IAAY,EAAM,MAAM,IACxB,IAAW,EAAM,MAAM,EAAE,CAAC,KAAK,IAAI;;CAGrC,IAAM,IAAQ,GAAa,SAAS,IAC9B,IAAS,GAAa,QACtB,IAAO,GAAa,MACpB,IAAc,GAAa,QAAQ,GAAG,EAAU,GAAG,IAAW,MAAM,IAAI,KAAS,gBAEjF,IAAW,GAAG,EAAU,OAAO,EAAE,GAAG,EAAS,OAAO,EAAE,GAAG,aAAa,IAAI,EAAM,OAAO,EAAE,CAAC,aAAa,IAAI,KAE3G,UAAsB,OAAO,SAAS,OAAO,EAAoB;AAEvE,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SAAQ;EACR,SACE,kBAAC,UAAD;GACE,SAAS;GACT,WAAU;aAFZ,CAIE,kBAAC,GAAD,EAAc,WAAU,eAAgB,CAAA,EAAA,sBAEjC;;YAXb,CAeE,kBAAC,GAAD;GAAe,WAAU;aACvB,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eACZ,IAAS,kBAAC,OAAD;MAAK,KAAK;MAAQ,KAAK;MAAa,WAAU;MAA+B,CAAA,GAAG;KACtF,CAAA,EAGN,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,MAAD;OAAI,WAAU;iBAA2C;OAAiB,CAAA;MAC1E,kBAAC,OAAD;OAAK,WAAU;iBACZ,KACC,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA,EAC/B,EACI;;OAEL,CAAA;MACL,KACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC3B,EACI;;OACH,CAAA;MAEJ;OACF;;GACQ,CAAA,EAGhB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAA4C;KAAyB,CAAA,EACnF,kBAAC,UAAD;KACE,SAAS;KACT,WAAU;eAFZ,CAIE,kBAAC,GAAD,EAAc,WAAU,eAAgB,CAAA,EAAA,sBAEjC;OACL;OACN,kBAAC,MAAD;IAAI,WAAU;cAAd;KACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAe,CAAA,EAC5E,kBAAC,MAAD;MAAI,WAAU;gBAA6B,KAAa;MAAS,CAAA,CAC7D,EAAA,CAAA;KACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAc,CAAA,EAC3E,kBAAC,MAAD;MAAI,WAAU;gBAA6B,KAAY;MAAS,CAAA,CAC5D,EAAA,CAAA;KACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAU,CAAA,EACvE,kBAAC,MAAD;MAAI,WAAU;gBAA6B,KAAS;MAAS,CAAA,CACzD,EAAA,CAAA;KACL,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAS,CAAA,EACtE,kBAAC,MAAD;MAAI,WAAU;gBAA6B;MAAU,CAAA,CACjD,EAAA,CAAA;KAEL;MACD;KACK"}
1
+ {"version":3,"file":"ProfilePage.js","names":[],"sources":["../../../../src/housingvista/pages/settings/ProfilePage.tsx"],"sourcesContent":["import { User, Mail, ExternalLink } from 'lucide-react';\nimport { EmphasisPanel } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components';\nimport { useHousingVista } from '../../context/HousingVistaContext';\nimport { useTrackPageView } from '../../hooks/useHousingVistaAnalytics';\n\n/**\n * Read-only profile view. This MFE exposes no profile-update mutation — account\n * identity (name, email, avatar, photo, role) is owned by the platform app shell.\n * We render what the shell hands us via `currentUser` and link out to the shell\n * account settings to make any change, rather than presenting a Save button that\n * cannot persist.\n */\nconst SHELL_ACCOUNT_ROUTE = '/auth/security';\n\nexport function ProfilePage() {\n useTrackPageView('housingvista.profile.viewed');\n const { currentUser } = useHousingVista();\n\n let firstName = currentUser?.firstName ?? '';\n let lastName = currentUser?.lastName ?? '';\n if (!firstName && !lastName && currentUser?.name) {\n const parts = currentUser.name.trim().split(/\\s+/).filter(Boolean);\n firstName = parts[0] ?? '';\n lastName = parts.slice(1).join(' ');\n }\n\n const email = currentUser?.email ?? '';\n const avatar = currentUser?.avatar;\n const role = currentUser?.role;\n const displayName = currentUser?.name || `${firstName} ${lastName}`.trim() || email || 'Your profile';\n\n const initials = `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase() || email.charAt(0).toUpperCase() || '?';\n\n const manageProfile = () => window.location.assign(SHELL_ACCOUNT_ROUTE);\n\n return (\n <PageLayout\n title=\"My Profile\"\n description=\"Your personal information across HousingVista\"\n purpose=\"Your identity across HousingVista. This is how owners, agents, and service providers see you on your listings and deals. Your account details are managed by the platform — use “Manage your profile” to update them.\"\n actions={\n <button\n onClick={manageProfile}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n Manage your profile\n </button>\n }\n >\n {/* Profile Card — primary emphasis zone (one per page) */}\n <EmphasisPanel className=\"p-6\">\n <div className=\"flex flex-col items-center gap-4 sm:flex-row sm:items-start\">\n {/* Avatar */}\n <div className=\"flex h-24 w-24 items-center justify-center overflow-hidden rounded-full bg-bg-sunken text-2xl font-bold text-text-primary\">\n {avatar ? <img src={avatar} alt={displayName} className=\"h-full w-full object-cover\" /> : initials}\n </div>\n\n {/* Info */}\n <div className=\"flex-1 text-center sm:text-left\">\n <h2 className=\"text-xl font-semibold text-text-primary\">{displayName}</h2>\n <div className=\"mt-1 flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-3\">\n {email && (\n <span className=\"flex items-center justify-center gap-1 text-sm text-text-secondary sm:justify-start\">\n <Mail className=\"h-3.5 w-3.5\" />\n {email}\n </span>\n )}\n </div>\n {role && (\n <div className=\"mt-2\">\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-primary\">\n <User className=\"h-3 w-3\" />\n {role}\n </span>\n </div>\n )}\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Personal Information — read-only */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"mb-4 flex items-center justify-between gap-4\">\n <h3 className=\"text-base font-semibold text-text-primary\">Personal Information</h3>\n <button\n onClick={manageProfile}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ExternalLink className=\"h-3.5 w-3.5\" />\n Manage your profile\n </button>\n </div>\n <dl className=\"grid gap-5 sm:grid-cols-2\">\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">First Name</dt>\n <dd className=\"text-sm text-text-primary\">{firstName || '—'}</dd>\n </div>\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">Last Name</dt>\n <dd className=\"text-sm text-text-primary\">{lastName || '—'}</dd>\n </div>\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">Email</dt>\n <dd className=\"text-sm text-text-primary\">{email || '—'}</dd>\n </div>\n {role && (\n <div>\n <dt className=\"mb-1 text-sm font-medium text-text-secondary\">Role</dt>\n <dd className=\"text-sm text-text-primary\">{role}</dd>\n </div>\n )}\n </dl>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;AAaA,IAAM,IAAsB;AAE5B,SAAgB,IAAc;AAC5B,GAAiB,8BAA8B;CAC/C,IAAM,EAAE,mBAAgB,GAAiB,EAErC,IAAY,GAAa,aAAa,IACtC,IAAW,GAAa,YAAY;AACxC,KAAI,CAAC,KAAa,CAAC,KAAY,GAAa,MAAM;EAChD,IAAM,IAAQ,EAAY,KAAK,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,QAAQ;AAElE,EADA,IAAY,EAAM,MAAM,IACxB,IAAW,EAAM,MAAM,EAAE,CAAC,KAAK,IAAI;;CAGrC,IAAM,IAAQ,GAAa,SAAS,IAC9B,IAAS,GAAa,QACtB,IAAO,GAAa,MACpB,IAAc,GAAa,QAAQ,GAAG,EAAU,GAAG,IAAW,MAAM,IAAI,KAAS,gBAEjF,IAAW,GAAG,EAAU,OAAO,EAAE,GAAG,EAAS,OAAO,EAAE,GAAG,aAAa,IAAI,EAAM,OAAO,EAAE,CAAC,aAAa,IAAI,KAE3G,UAAsB,OAAO,SAAS,OAAO,EAAoB;AAEvE,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SAAQ;EACR,SACE,kBAAC,UAAD;GACE,SAAS;GACT,WAAU;aAFZ,CAIE,kBAAC,GAAD,EAAc,WAAU,eAAgB,CAAA,EAAA,sBAEjC;;YAXb,CAeE,kBAAC,GAAD;GAAe,WAAU;aACvB,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eACZ,IAAS,kBAAC,OAAD;MAAK,KAAK;MAAQ,KAAK;MAAa,WAAU;MAA+B,CAAA,GAAG;KACtF,CAAA,EAGN,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,MAAD;OAAI,WAAU;iBAA2C;OAAiB,CAAA;MAC1E,kBAAC,OAAD;OAAK,WAAU;iBACZ,KACC,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA,EAC/B,EACI;;OAEL,CAAA;MACL,KACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC3B,EACI;;OACH,CAAA;MAEJ;OACF;;GACQ,CAAA,EAGhB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAA4C;KAAyB,CAAA,EACnF,kBAAC,UAAD;KACE,SAAS;KACT,WAAU;eAFZ,CAIE,kBAAC,GAAD,EAAc,WAAU,eAAgB,CAAA,EAAA,sBAEjC;OACL;OACN,kBAAC,MAAD;IAAI,WAAU;cAAd;KACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAe,CAAA,EAC5E,kBAAC,MAAD;MAAI,WAAU;gBAA6B,KAAa;MAAS,CAAA,CAC7D,EAAA,CAAA;KACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAc,CAAA,EAC3E,kBAAC,MAAD;MAAI,WAAU;gBAA6B,KAAY;MAAS,CAAA,CAC5D,EAAA,CAAA;KACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAU,CAAA,EACvE,kBAAC,MAAD;MAAI,WAAU;gBAA6B,KAAS;MAAS,CAAA,CACzD,EAAA,CAAA;KACL,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;MAAI,WAAU;gBAA+C;MAAS,CAAA,EACtE,kBAAC,MAAD;MAAI,WAAU;gBAA6B;MAAU,CAAA,CACjD,EAAA,CAAA;KAEL;MACD;KACK"}
@@ -1 +1 @@
1
- {"version":3,"file":"SettingsPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/settings/SettingsPage.tsx"],"names":[],"mappings":"AA6CA,wBAAgB,YAAY,gCA8E3B"}
1
+ {"version":3,"file":"SettingsPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/settings/SettingsPage.tsx"],"names":[],"mappings":"AA8CA,wBAAgB,YAAY,gCA+E3B"}