@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":"HomeLoansPage.js","names":[],"sources":["../../../../src/housingvista/pages/finance/HomeLoansPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Building2, Calculator, Star, CheckCircle, ArrowRight, Gift } from 'lucide-react';\nimport { EmphasisPanel, NextSteps, Pagination } from '@burdenoff/fe-libs/ui';\nimport { PageLayout, EmptyState, FilterBar, LoadingSkeleton } from '../../components';\nimport { useHomeLoans } from '../../hooks';\nimport { useServerPagination } from '../../hooks/useServerPagination';\nimport { cn, formatCurrency, formatINRCompact } from '../../utils/helpers';\nimport type { HomeLoan } from '../../types';\n\nconst PAGE_SIZE = 9;\n\n/** Branded emerald range slider (matches the mock's green sliders). */\nconst SLIDER_CLASS = 'w-full accent-[var(--color-action-primary-bg)]';\n\nfunction calculateEMI(principal: number, annualRate: number, tenureYears: number): number {\n if (principal <= 0 || annualRate <= 0 || tenureYears <= 0) return 0;\n const monthlyRate = annualRate / 12 / 100;\n const months = tenureYears * 12;\n const emi = (principal * monthlyRate * Math.pow(1 + monthlyRate, months)) / (Math.pow(1 + monthlyRate, months) - 1);\n return Math.round(emi);\n}\n\nfunction RatingStars({ rating }: { rating: number }) {\n return (\n <div className=\"flex items-center gap-0.5 text-status-warning-text\">\n {Array.from({ length: 5 }).map((_, i) => (\n <Star\n key={i}\n className={cn('h-3 w-3', i < Math.floor(rating) ? 'fill-current' : 'fill-none text-text-secondary/30')}\n />\n ))}\n </div>\n );\n}\n\nfunction LoanCard({ loan }: { loan: HomeLoan }) {\n const navigate = useNavigate();\n\n return (\n <div className=\"flex flex-col rounded-card border border-border-seam bg-bg-surface p-5 shadow-elevation-1 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-elevation-2\">\n {/* Header */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-accent-blue-subtle\">\n <Building2 className=\"h-6 w-6 text-accent-blue\" />\n </div>\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">{loan.bankName}</h3>\n <div className=\"flex items-center gap-1.5 mt-0.5\">\n <RatingStars rating={loan.rating} />\n <span className=\"text-xs text-text-secondary\">{loan.rating}</span>\n </div>\n </div>\n </div>\n {loan.specialOffer && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs font-medium text-status-warning-text\">\n <Gift className=\"h-3 w-3\" />\n Offer\n </span>\n )}\n </div>\n\n {/* Key Stats Grid */}\n <div className=\"mb-4 grid grid-cols-2 gap-3\">\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">Interest Rate</p>\n <p className=\"text-lg font-bold text-text-primary\">{loan.interestRate}%</p>\n </div>\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">EMI / Lakh</p>\n <p className=\"text-lg font-bold text-text-primary\">{formatINRCompact(loan.emiPerLakh)}</p>\n </div>\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">Max Tenure</p>\n <p className=\"text-sm font-semibold text-text-primary\">{loan.maxTenure} years</p>\n </div>\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">Max Amount</p>\n <p className=\"text-sm font-semibold text-text-primary\">{formatINRCompact(loan.maxAmount)}</p>\n </div>\n </div>\n\n {/* Processing Fee */}\n <div className=\"mb-3 flex items-center justify-between text-xs\">\n <span className=\"text-text-secondary\">Processing Fee</span>\n <span className=\"font-medium text-text-primary\">{loan.processingFee}</span>\n </div>\n\n {/* Prepayment Charges */}\n <div className=\"mb-3 flex items-center justify-between text-xs\">\n <span className=\"text-text-secondary\">Prepayment Charges</span>\n <span\n className={cn(\n 'font-medium',\n loan.prepaymentCharges === 'None' ? 'text-status-success-text' : 'text-text-primary'\n )}\n >\n {loan.prepaymentCharges}\n </span>\n </div>\n\n {/* Special Offer */}\n {loan.specialOffer && (\n <div className=\"mb-3 rounded-md bg-status-warning-bg-subtle p-2.5 text-xs text-status-warning-text\">\n {loan.specialOffer}\n </div>\n )}\n\n {/* Features */}\n <div className=\"mb-4 space-y-1.5\">\n {loan.features.map((feature, i) => (\n <div key={i} className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <CheckCircle className=\"h-3 w-3 shrink-0 text-status-success-text\" />\n {feature}\n </div>\n ))}\n </div>\n\n {/* Apply Button */}\n <button\n onClick={() => navigate(`../home-loans/${loan.id}/apply`)}\n className=\"mt-auto flex w-full items-center justify-center gap-1.5 rounded-md bg-action-primary-bg px-4 py-2.5 text-xs font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n Apply Now\n <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n );\n}\n\nexport function HomeLoansPage() {\n const navigate = useNavigate();\n const pagination = useServerPagination(PAGE_SIZE);\n const { data: loans, loading } = useHomeLoans(pagination.pagination);\n\n // Home-loan offers have no server-side filter input — search refines the\n // fetched page client-side; pagination stays server-side.\n const [search, setSearch] = useState('');\n const filteredLoans = useMemo(() => {\n const term = search.trim().toLowerCase();\n if (!term) return loans;\n return loans.filter(\n (loan) =>\n loan.bankName.toLowerCase().includes(term) ||\n loan.features.some((feature) => feature.toLowerCase().includes(term)) ||\n (loan.specialOffer ?? '').toLowerCase().includes(term)\n );\n }, [loans, search]);\n\n const hasNextPage = loans.length >= pagination.pageSize;\n\n // EMI Calculator state\n const [loanAmount, setLoanAmount] = useState(5000000);\n const [tenure, setTenure] = useState(20);\n const [interestRate, setInterestRate] = useState(6.75);\n\n const emi = useMemo(() => calculateEMI(loanAmount, interestRate, tenure), [loanAmount, interestRate, tenure]);\n const totalPayment = emi * tenure * 12;\n const totalInterest = totalPayment - loanAmount;\n\n return (\n <PageLayout\n title=\"Home Loans\"\n description=\"Compare rates, calculate EMI, and apply for home loans\"\n purpose=\"Work out what a home loan will really cost before you commit. Use the EMI calculator to model your monthly payment and total interest, then compare offers from partner banks and apply to the one that fits.\"\n >\n {/* EMI Calculator — primary emphasis zone (one per page) */}\n <EmphasisPanel className=\"p-5\">\n <div className=\"mb-4 flex items-center gap-2\">\n <Calculator className=\"h-5 w-5 text-text-secondary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">EMI Calculator</h2>\n </div>\n\n <div className=\"grid gap-6 md:grid-cols-2\">\n {/* Inputs */}\n <div className=\"space-y-5\">\n {/* Loan Amount */}\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm font-medium text-text-primary\">Loan Amount</label>\n <span className=\"text-sm font-semibold text-text-primary\">{formatCurrency(loanAmount)}</span>\n </div>\n <input\n type=\"range\"\n min={100000}\n max={50000000}\n step={100000}\n value={loanAmount}\n onChange={(e) => setLoanAmount(Number(e.target.value))}\n aria-label=\"Loan amount\"\n className={SLIDER_CLASS}\n />\n <div className=\"flex justify-between text-xs text-text-secondary mt-1\">\n <span>₹1 L</span>\n <span>₹5 Cr</span>\n </div>\n </div>\n\n {/* Tenure */}\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm font-medium text-text-primary\">Tenure (years)</label>\n <span className=\"text-sm font-semibold text-text-primary\">{tenure} years</span>\n </div>\n <input\n type=\"range\"\n min={1}\n max={30}\n step={1}\n value={tenure}\n onChange={(e) => setTenure(Number(e.target.value))}\n className={SLIDER_CLASS}\n />\n <div className=\"flex justify-between text-xs text-text-secondary mt-1\">\n <span>1 yr</span>\n <span>30 yrs</span>\n </div>\n </div>\n\n {/* Interest Rate */}\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm font-medium text-text-primary\">Interest Rate (%)</label>\n <span className=\"text-sm font-semibold text-text-primary\">{interestRate}%</span>\n </div>\n <input\n type=\"range\"\n min={3}\n max={15}\n step={0.05}\n value={interestRate}\n onChange={(e) => setInterestRate(Number(e.target.value))}\n className={SLIDER_CLASS}\n />\n <div className=\"flex justify-between text-xs text-text-secondary mt-1\">\n <span>3%</span>\n <span>15%</span>\n </div>\n </div>\n </div>\n\n {/* Results */}\n <div className=\"flex flex-col items-center justify-center rounded-lg bg-bg-sunken/50 p-6\">\n <p className=\"text-sm text-text-secondary\">Monthly EMI</p>\n <p className=\"my-2 text-4xl font-bold text-text-primary\">{formatCurrency(emi)}</p>\n <div className=\"mt-4 grid w-full grid-cols-2 gap-4\">\n <div className=\"text-center\">\n <p className=\"text-xs text-text-secondary\">Total Payment</p>\n <p className=\"text-sm font-semibold text-text-primary\">{formatCurrency(totalPayment)}</p>\n </div>\n <div className=\"text-center\">\n <p className=\"text-xs text-text-secondary\">Total Interest</p>\n <p className=\"text-sm font-semibold text-status-error-text\">{formatCurrency(totalInterest)}</p>\n </div>\n </div>\n {/* Visual breakdown bar */}\n <div className=\"mt-4 w-full\">\n <div className=\"flex h-3 w-full overflow-hidden rounded-full\">\n <div className=\"bg-chart-1 transition-all\" style={{ width: `${(loanAmount / totalPayment) * 100}%` }} />\n <div\n className=\"bg-chart-negative transition-all\"\n style={{ width: `${(totalInterest / totalPayment) * 100}%` }}\n />\n </div>\n <div className=\"mt-1.5 flex justify-between text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded-full bg-chart-1\" /> Principal\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded-full bg-chart-negative\" /> Interest\n </span>\n </div>\n </div>\n </div>\n </div>\n </EmphasisPanel>\n\n <NextSteps\n storageKey=\"housingvista-home-loans\"\n steps={[\n {\n id: 'apply-best',\n label: 'Apply to the best-rated offer',\n description: 'Start an application with a top partner bank.',\n onClick: () => {\n const best = [...loans].sort((a, b) => b.rating - a.rating)[0];\n if (best) navigate(`../home-loans/${best.id}/apply`);\n },\n },\n {\n id: 'browse-properties',\n label: 'Find a property to finance',\n description: 'Browse listings that fit the amount you just modeled.',\n onClick: () => navigate('../properties'),\n },\n {\n id: 'track-transactions',\n label: 'Track your purchase',\n description: 'See ongoing deals where this loan would apply.',\n onClick: () => navigate('../transactions'),\n },\n ]}\n />\n\n {/* Loan Offers */}\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Available Loan Offers</h2>\n\n {/* Search — refines the fetched page */}\n <FilterBar\n searchValue={search}\n onSearchChange={setSearch}\n searchPlaceholder=\"Search banks, features, offers on this page...\"\n />\n\n {loading ? (\n <LoadingSkeleton variant=\"card\" count={6} />\n ) : filteredLoans.length > 0 ? (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filteredLoans.map((loan) => (\n <LoanCard key={loan.id} loan={loan} />\n ))}\n </div>\n <Pagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n hasNextPage={hasNextPage}\n hasPreviousPage={pagination.page > 1}\n onPageChange={pagination.setPage}\n onPageSizeChange={pagination.setPageSize}\n />\n </>\n ) : (\n <EmptyState\n illustration={search ? 'empty-search' : 'empty-data'}\n icon={<Building2 className=\"h-12 w-12\" />}\n title={search ? 'No matching loan offers' : 'No loan offers available'}\n description={\n search\n ? 'No offers on this page match your search. Clear the search or try another page.'\n : 'Check back later for new loan offers from our partner banks.'\n }\n />\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"HomeLoansPage.js","names":[],"sources":["../../../../src/housingvista/pages/finance/HomeLoansPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Building2, Calculator, Star, CheckCircle, ArrowRight, Gift } from 'lucide-react';\nimport { EmphasisPanel, NextSteps, Pagination } from '@burdenoff/fe-libs/ui';\nimport { PageLayout, EmptyState, FilterBar, LoadingSkeleton } from '../../components';\nimport { useHomeLoans } from '../../hooks';\nimport { useServerPagination } from '../../hooks/useServerPagination';\nimport { cn, formatCurrency, formatINRCompact } from '../../utils/helpers';\nimport type { HomeLoan } from '../../types';\nimport { useTrackPageView } from '../../hooks/useHousingVistaAnalytics';\n\nconst PAGE_SIZE = 9;\n\n/** Branded emerald range slider (matches the mock's green sliders). */\nconst SLIDER_CLASS = 'w-full accent-[var(--color-action-primary-bg)]';\n\nfunction calculateEMI(principal: number, annualRate: number, tenureYears: number): number {\n if (principal <= 0 || annualRate <= 0 || tenureYears <= 0) return 0;\n const monthlyRate = annualRate / 12 / 100;\n const months = tenureYears * 12;\n const emi = (principal * monthlyRate * Math.pow(1 + monthlyRate, months)) / (Math.pow(1 + monthlyRate, months) - 1);\n return Math.round(emi);\n}\n\nfunction RatingStars({ rating }: { rating: number }) {\n return (\n <div className=\"flex items-center gap-0.5 text-status-warning-text\">\n {Array.from({ length: 5 }).map((_, i) => (\n <Star\n key={i}\n className={cn('h-3 w-3', i < Math.floor(rating) ? 'fill-current' : 'fill-none text-text-secondary/30')}\n />\n ))}\n </div>\n );\n}\n\nfunction LoanCard({ loan }: { loan: HomeLoan }) {\n const navigate = useNavigate();\n\n return (\n <div className=\"flex flex-col rounded-card border border-border-seam bg-bg-surface p-5 shadow-elevation-1 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-elevation-2\">\n {/* Header */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-accent-blue-subtle\">\n <Building2 className=\"h-6 w-6 text-accent-blue\" />\n </div>\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">{loan.bankName}</h3>\n <div className=\"flex items-center gap-1.5 mt-0.5\">\n <RatingStars rating={loan.rating} />\n <span className=\"text-xs text-text-secondary\">{loan.rating}</span>\n </div>\n </div>\n </div>\n {loan.specialOffer && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs font-medium text-status-warning-text\">\n <Gift className=\"h-3 w-3\" />\n Offer\n </span>\n )}\n </div>\n\n {/* Key Stats Grid */}\n <div className=\"mb-4 grid grid-cols-2 gap-3\">\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">Interest Rate</p>\n <p className=\"text-lg font-bold text-text-primary\">{loan.interestRate}%</p>\n </div>\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">EMI / Lakh</p>\n <p className=\"text-lg font-bold text-text-primary\">{formatINRCompact(loan.emiPerLakh)}</p>\n </div>\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">Max Tenure</p>\n <p className=\"text-sm font-semibold text-text-primary\">{loan.maxTenure} years</p>\n </div>\n <div className=\"rounded-md bg-bg-sunken/50 p-2.5\">\n <p className=\"text-xs text-text-secondary\">Max Amount</p>\n <p className=\"text-sm font-semibold text-text-primary\">{formatINRCompact(loan.maxAmount)}</p>\n </div>\n </div>\n\n {/* Processing Fee */}\n <div className=\"mb-3 flex items-center justify-between text-xs\">\n <span className=\"text-text-secondary\">Processing Fee</span>\n <span className=\"font-medium text-text-primary\">{loan.processingFee}</span>\n </div>\n\n {/* Prepayment Charges */}\n <div className=\"mb-3 flex items-center justify-between text-xs\">\n <span className=\"text-text-secondary\">Prepayment Charges</span>\n <span\n className={cn(\n 'font-medium',\n loan.prepaymentCharges === 'None' ? 'text-status-success-text' : 'text-text-primary'\n )}\n >\n {loan.prepaymentCharges}\n </span>\n </div>\n\n {/* Special Offer */}\n {loan.specialOffer && (\n <div className=\"mb-3 rounded-md bg-status-warning-bg-subtle p-2.5 text-xs text-status-warning-text\">\n {loan.specialOffer}\n </div>\n )}\n\n {/* Features */}\n <div className=\"mb-4 space-y-1.5\">\n {loan.features.map((feature, i) => (\n <div key={i} className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <CheckCircle className=\"h-3 w-3 shrink-0 text-status-success-text\" />\n {feature}\n </div>\n ))}\n </div>\n\n {/* Apply Button */}\n <button\n onClick={() => navigate(`../home-loans/${loan.id}/apply`)}\n className=\"mt-auto flex w-full items-center justify-center gap-1.5 rounded-md bg-action-primary-bg px-4 py-2.5 text-xs font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n Apply Now\n <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n );\n}\n\nexport function HomeLoansPage() {\n useTrackPageView('housingvista.home_loan.viewed');\n const navigate = useNavigate();\n const pagination = useServerPagination(PAGE_SIZE);\n const { data: loans, loading } = useHomeLoans(pagination.pagination);\n\n // Home-loan offers have no server-side filter input — search refines the\n // fetched page client-side; pagination stays server-side.\n const [search, setSearch] = useState('');\n const filteredLoans = useMemo(() => {\n const term = search.trim().toLowerCase();\n if (!term) return loans;\n return loans.filter(\n (loan) =>\n loan.bankName.toLowerCase().includes(term) ||\n loan.features.some((feature) => feature.toLowerCase().includes(term)) ||\n (loan.specialOffer ?? '').toLowerCase().includes(term)\n );\n }, [loans, search]);\n\n const hasNextPage = loans.length >= pagination.pageSize;\n\n // EMI Calculator state\n const [loanAmount, setLoanAmount] = useState(5000000);\n const [tenure, setTenure] = useState(20);\n const [interestRate, setInterestRate] = useState(6.75);\n\n const emi = useMemo(() => calculateEMI(loanAmount, interestRate, tenure), [loanAmount, interestRate, tenure]);\n const totalPayment = emi * tenure * 12;\n const totalInterest = totalPayment - loanAmount;\n\n return (\n <PageLayout\n title=\"Home Loans\"\n description=\"Compare rates, calculate EMI, and apply for home loans\"\n purpose=\"Work out what a home loan will really cost before you commit. Use the EMI calculator to model your monthly payment and total interest, then compare offers from partner banks and apply to the one that fits.\"\n >\n {/* EMI Calculator — primary emphasis zone (one per page) */}\n <EmphasisPanel className=\"p-5\">\n <div className=\"mb-4 flex items-center gap-2\">\n <Calculator className=\"h-5 w-5 text-text-secondary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">EMI Calculator</h2>\n </div>\n\n <div className=\"grid gap-6 md:grid-cols-2\">\n {/* Inputs */}\n <div className=\"space-y-5\">\n {/* Loan Amount */}\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm font-medium text-text-primary\">Loan Amount</label>\n <span className=\"text-sm font-semibold text-text-primary\">{formatCurrency(loanAmount)}</span>\n </div>\n <input\n type=\"range\"\n min={100000}\n max={50000000}\n step={100000}\n value={loanAmount}\n onChange={(e) => setLoanAmount(Number(e.target.value))}\n aria-label=\"Loan amount\"\n className={SLIDER_CLASS}\n />\n <div className=\"flex justify-between text-xs text-text-secondary mt-1\">\n <span>₹1 L</span>\n <span>₹5 Cr</span>\n </div>\n </div>\n\n {/* Tenure */}\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm font-medium text-text-primary\">Tenure (years)</label>\n <span className=\"text-sm font-semibold text-text-primary\">{tenure} years</span>\n </div>\n <input\n type=\"range\"\n min={1}\n max={30}\n step={1}\n value={tenure}\n onChange={(e) => setTenure(Number(e.target.value))}\n className={SLIDER_CLASS}\n />\n <div className=\"flex justify-between text-xs text-text-secondary mt-1\">\n <span>1 yr</span>\n <span>30 yrs</span>\n </div>\n </div>\n\n {/* Interest Rate */}\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm font-medium text-text-primary\">Interest Rate (%)</label>\n <span className=\"text-sm font-semibold text-text-primary\">{interestRate}%</span>\n </div>\n <input\n type=\"range\"\n min={3}\n max={15}\n step={0.05}\n value={interestRate}\n onChange={(e) => setInterestRate(Number(e.target.value))}\n className={SLIDER_CLASS}\n />\n <div className=\"flex justify-between text-xs text-text-secondary mt-1\">\n <span>3%</span>\n <span>15%</span>\n </div>\n </div>\n </div>\n\n {/* Results */}\n <div className=\"flex flex-col items-center justify-center rounded-lg bg-bg-sunken/50 p-6\">\n <p className=\"text-sm text-text-secondary\">Monthly EMI</p>\n <p className=\"my-2 text-4xl font-bold text-text-primary\">{formatCurrency(emi)}</p>\n <div className=\"mt-4 grid w-full grid-cols-2 gap-4\">\n <div className=\"text-center\">\n <p className=\"text-xs text-text-secondary\">Total Payment</p>\n <p className=\"text-sm font-semibold text-text-primary\">{formatCurrency(totalPayment)}</p>\n </div>\n <div className=\"text-center\">\n <p className=\"text-xs text-text-secondary\">Total Interest</p>\n <p className=\"text-sm font-semibold text-status-error-text\">{formatCurrency(totalInterest)}</p>\n </div>\n </div>\n {/* Visual breakdown bar */}\n <div className=\"mt-4 w-full\">\n <div className=\"flex h-3 w-full overflow-hidden rounded-full\">\n <div className=\"bg-chart-1 transition-all\" style={{ width: `${(loanAmount / totalPayment) * 100}%` }} />\n <div\n className=\"bg-chart-negative transition-all\"\n style={{ width: `${(totalInterest / totalPayment) * 100}%` }}\n />\n </div>\n <div className=\"mt-1.5 flex justify-between text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded-full bg-chart-1\" /> Principal\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded-full bg-chart-negative\" /> Interest\n </span>\n </div>\n </div>\n </div>\n </div>\n </EmphasisPanel>\n\n <NextSteps\n storageKey=\"housingvista-home-loans\"\n steps={[\n {\n id: 'apply-best',\n label: 'Apply to the best-rated offer',\n description: 'Start an application with a top partner bank.',\n onClick: () => {\n const best = [...loans].sort((a, b) => b.rating - a.rating)[0];\n if (best) navigate(`../home-loans/${best.id}/apply`);\n },\n },\n {\n id: 'browse-properties',\n label: 'Find a property to finance',\n description: 'Browse listings that fit the amount you just modeled.',\n onClick: () => navigate('../properties'),\n },\n {\n id: 'track-transactions',\n label: 'Track your purchase',\n description: 'See ongoing deals where this loan would apply.',\n onClick: () => navigate('../transactions'),\n },\n ]}\n />\n\n {/* Loan Offers */}\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Available Loan Offers</h2>\n\n {/* Search — refines the fetched page */}\n <FilterBar\n searchValue={search}\n onSearchChange={setSearch}\n searchPlaceholder=\"Search banks, features, offers on this page...\"\n />\n\n {loading ? (\n <LoadingSkeleton variant=\"card\" count={6} />\n ) : filteredLoans.length > 0 ? (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filteredLoans.map((loan) => (\n <LoanCard key={loan.id} loan={loan} />\n ))}\n </div>\n <Pagination\n page={pagination.page}\n pageSize={pagination.pageSize}\n hasNextPage={hasNextPage}\n hasPreviousPage={pagination.page > 1}\n onPageChange={pagination.setPage}\n onPageSizeChange={pagination.setPageSize}\n />\n </>\n ) : (\n <EmptyState\n illustration={search ? 'empty-search' : 'empty-data'}\n icon={<Building2 className=\"h-12 w-12\" />}\n title={search ? 'No matching loan offers' : 'No loan offers available'}\n description={\n search\n ? 'No offers on this page match your search. Clear the search or try another page.'\n : 'Check back later for new loan offers from our partner banks.'\n }\n />\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"InvestmentDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/investments/InvestmentDetailPage.tsx"],"names":[],"mappings":"AAwIA,wBAAgB,oBAAoB,gCA8kBnC"}
1
+ {"version":3,"file":"InvestmentDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/investments/InvestmentDetailPage.tsx"],"names":[],"mappings":"AAyIA,wBAAgB,oBAAoB,gCAglBnC"}