@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.
- package/dist/housingvista/HousingVistaRoutes.d.ts.map +1 -1
- package/dist/housingvista/HousingVistaRoutes.js +136 -37
- package/dist/housingvista/HousingVistaRoutes.js.map +1 -1
- package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts +1 -1
- package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts.map +1 -1
- package/dist/housingvista/hooks/useHousingVistaAnalytics.js +4 -4
- package/dist/housingvista/hooks/useHousingVistaAnalytics.js.map +1 -1
- package/dist/housingvista/pages/amc/AMCManagementPage.d.ts.map +1 -1
- package/dist/housingvista/pages/amc/AMCManagementPage.js +62 -60
- package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
- package/dist/housingvista/pages/assets/AssetDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/assets/AssetDetailPage.js +141 -138
- package/dist/housingvista/pages/assets/AssetDetailPage.js.map +1 -1
- package/dist/housingvista/pages/assets/AssetManagementPage.d.ts.map +1 -1
- package/dist/housingvista/pages/assets/AssetManagementPage.js +193 -191
- package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
- package/dist/housingvista/pages/chat/ChatPage.d.ts.map +1 -1
- package/dist/housingvista/pages/chat/ChatPage.js +115 -113
- package/dist/housingvista/pages/chat/ChatPage.js.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.js +152 -149
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.js.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoansPage.d.ts.map +1 -1
- package/dist/housingvista/pages/finance/HomeLoansPage.js +141 -139
- package/dist/housingvista/pages/finance/HomeLoansPage.js.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentDetailPage.js +290 -287
- package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/investments/InvestmentsPage.js +64 -62
- package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
- package/dist/housingvista/pages/legal/LegalPage.d.ts.map +1 -1
- package/dist/housingvista/pages/legal/LegalPage.js +95 -93
- package/dist/housingvista/pages/legal/LegalPage.js.map +1 -1
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.js +129 -126
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.js.map +1 -1
- package/dist/housingvista/pages/market/AreaInsightsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/market/AreaInsightsPage.js +99 -97
- package/dist/housingvista/pages/market/AreaInsightsPage.js.map +1 -1
- package/dist/housingvista/pages/market/MarketAnalyticsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/market/MarketAnalyticsPage.js +138 -136
- package/dist/housingvista/pages/market/MarketAnalyticsPage.js.map +1 -1
- package/dist/housingvista/pages/marketplace/MarketplacePage.d.ts.map +1 -1
- package/dist/housingvista/pages/marketplace/MarketplacePage.js +99 -97
- package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.js +137 -134
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.js.map +1 -1
- package/dist/housingvista/pages/offers/OffersPage.d.ts.map +1 -1
- package/dist/housingvista/pages/offers/OffersPage.js +94 -92
- package/dist/housingvista/pages/offers/OffersPage.js.map +1 -1
- package/dist/housingvista/pages/properties/AddPropertyPage.d.ts.map +1 -1
- package/dist/housingvista/pages/properties/AddPropertyPage.js +280 -279
- package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
- package/dist/housingvista/pages/rental/RentalManagementPage.d.ts.map +1 -1
- package/dist/housingvista/pages/rental/RentalManagementPage.js +153 -151
- package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
- package/dist/housingvista/pages/settings/ProfilePage.d.ts.map +1 -1
- package/dist/housingvista/pages/settings/ProfilePage.js +52 -50
- package/dist/housingvista/pages/settings/ProfilePage.js.map +1 -1
- package/dist/housingvista/pages/settings/SettingsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/settings/SettingsPage.js +54 -52
- package/dist/housingvista/pages/settings/SettingsPage.js.map +1 -1
- package/dist/housingvista/pages/shortlist/ShortlistPage.d.ts.map +1 -1
- package/dist/housingvista/pages/shortlist/ShortlistPage.js +43 -41
- package/dist/housingvista/pages/shortlist/ShortlistPage.js.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionDetailPage.js +211 -208
- package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/transactions/TransactionsPage.js +85 -83
- package/dist/housingvista/pages/transactions/TransactionsPage.js.map +1 -1
- package/dist/housingvista/pages/verification/VerificationDetailPage.d.ts.map +1 -1
- package/dist/housingvista/pages/verification/VerificationDetailPage.js +25 -22
- package/dist/housingvista/pages/verification/VerificationDetailPage.js.map +1 -1
- package/dist/housingvista/pages/verification/VerificationPage.d.ts.map +1 -1
- package/dist/housingvista/pages/verification/VerificationPage.js +123 -121
- package/dist/housingvista/pages/verification/VerificationPage.js.map +1 -1
- package/dist/housingvista/pages/viewings/ViewingsPage.d.ts.map +1 -1
- package/dist/housingvista/pages/viewings/ViewingsPage.js +128 -126
- package/dist/housingvista/pages/viewings/ViewingsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HomeLoanDetailPage.js","names":[],"sources":["../../../../src/housingvista/pages/finance/HomeLoanDetailPage.tsx"],"sourcesContent":["/**\n * HousingVista Home Loan Detail / Apply Page\n * Single loan offer backed by `housingvistaHomeLoanOffer(id)` — full terms plus\n * a live EMI summary for the offer's headline rate.\n *\n * \"Apply\" opens the real `ContactOwnerDialog` — a persisted conversation with\n * the bank. No fabricated approval; the EMI calculator stays for modelling.\n * @module housingvista\n */\n\nimport { useMemo, useState } from 'react';\nimport { useNavigate, useParams, useLocation } from 'react-router-dom';\nimport {\n ArrowLeft,\n Building2,\n Star,\n CheckCircle,\n Gift,\n Calculator,\n Percent,\n Wallet,\n CalendarClock,\n} from 'lucide-react';\nimport { Button, EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { Breadcrumbs, StatusBadge, EmptyState, LoadingSkeleton, ContactOwnerDialog } from '../../components';\nimport type { BreadcrumbItem } from '../../components';\nimport { useHomeLoanOffer } from '../../hooks';\nimport { cn, formatCurrency, formatINRCompact } from '../../utils/helpers';\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-4 w-4', i < Math.floor(rating) ? 'fill-current' : 'fill-none text-text-secondary/30')}\n />\n ))}\n </div>\n );\n}\n\nexport function HomeLoanDetailPage() {\n const { id } = useParams<{ id: string }>();\n const navigate = useNavigate();\n const location = useLocation();\n const { data: loan, loading } = useHomeLoanOffer(id);\n\n // Model a representative loan against the offer's headline rate so the borrower\n // can see the real monthly cost before enquiring.\n const [amount, setAmount] = useState(500000);\n const [tenure, setTenure] = useState(20);\n const [contactOpen, setContactOpen] = useState(false);\n\n const rate = loan?.interestRate ?? 0;\n const emi = useMemo(() => calculateEMI(amount, rate, tenure), [amount, rate, tenure]);\n const totalPayment = emi * tenure * 12;\n const totalInterest = totalPayment - amount;\n\n if (loading) {\n return (\n <div className=\"p-6\">\n <LoadingSkeleton variant=\"detail\" />\n </div>\n );\n }\n\n if (!loan) {\n return (\n <div className=\"p-6\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<Building2 className=\"h-12 w-12\" />}\n title=\"Loan Offer Not Found\"\n description=\"The loan offer you're looking for doesn't exist or is no longer available.\"\n action={\n <button\n onClick={() => navigate('../home-loans')}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Home Loans\n </button>\n }\n />\n </div>\n );\n }\n\n const features = loan.features ?? [];\n const breadcrumbs: BreadcrumbItem[] = [{ label: 'Home Loans', href: '../' }, { label: loan.bankName }];\n\n return (\n <div className=\"flex flex-col gap-6 p-6\">\n <Breadcrumbs items={breadcrumbs} />\n\n {/* Header */}\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"flex items-start gap-4\">\n <div className=\"flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <Building2 className=\"h-6 w-6\" />\n </div>\n <div>\n <button\n onClick={() => navigate('../home-loans')}\n className=\"mb-2 inline-flex items-center gap-2 rounded-md px-2 py-1 text-sm text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Home Loans\n </button>\n <h1 className=\"text-2xl font-semibold text-text-primary\">{loan.bankName}</h1>\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n {loan.rating != null && (\n <span className=\"inline-flex items-center gap-1.5\">\n <RatingStars rating={loan.rating} />\n <span className=\"text-sm text-text-secondary\">{loan.rating}</span>\n </span>\n )}\n {loan.specialOffer && <StatusBadge label=\"Special Offer\" variant=\"warning\" />}\n </div>\n </div>\n </div>\n <Button type=\"button\" variant=\"default\" onClick={() => setContactOpen(true)}>\n Apply Now\n </Button>\n </div>\n\n <PagePurpose className=\"max-w-3xl\">\n The full terms of this offer with a live EMI estimate at the bank's headline rate. Model your loan amount and\n tenure to see the real monthly cost, then apply to connect with {loan.bankName} through Messages.\n </PagePurpose>\n\n {loan.specialOffer && (\n <div className=\"flex items-center gap-2 rounded-lg bg-status-warning-bg-subtle p-3 text-sm text-status-warning-text\">\n <Gift className=\"h-4 w-4 shrink-0\" />\n {loan.specialOffer}\n </div>\n )}\n\n {/* EMI summary — 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 Estimate at {loan.interestRate}%</h2>\n </div>\n <div className=\"grid gap-6 md:grid-cols-2\">\n <div className=\"space-y-5\">\n <div>\n <div className=\"mb-2 flex items-center justify-between\">\n <label className=\"text-sm font-medium text-text-primary\">Loan Amount</label>\n <span className=\"text-sm font-semibold text-text-primary\">{formatCurrency(amount)}</span>\n </div>\n <input\n type=\"range\"\n min={50000}\n max={Math.max(loan.maxAmount, 100000)}\n step={10000}\n value={Math.min(amount, loan.maxAmount)}\n onChange={(e) => setAmount(Number(e.target.value))}\n aria-label=\"Loan amount\"\n className={SLIDER_CLASS}\n />\n <div className=\"mt-1 flex justify-between text-xs text-text-secondary\">\n <span>₹50K</span>\n <span>Max {formatINRCompact(loan.maxAmount)}</span>\n </div>\n </div>\n <div>\n <div className=\"mb-2 flex items-center justify-between\">\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={loan.maxTenure}\n step={1}\n value={Math.min(tenure, loan.maxTenure)}\n onChange={(e) => setTenure(Number(e.target.value))}\n aria-label=\"Tenure in years\"\n className={SLIDER_CLASS}\n />\n <div className=\"mt-1 flex justify-between text-xs text-text-secondary\">\n <span>1 yr</span>\n <span>Max {loan.maxTenure} yrs</span>\n </div>\n </div>\n </div>\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 </div>\n </div>\n </EmphasisPanel>\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Terms */}\n <div className=\"space-y-6 lg:col-span-2\">\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Loan Terms</h2>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <Percent className=\"h-3.5 w-3.5\" />\n Interest Rate\n </div>\n <div className=\"mt-1 text-lg font-bold text-text-primary\">{loan.interestRate}%</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <Wallet className=\"h-3.5 w-3.5\" />\n EMI / Lakh\n </div>\n <div className=\"mt-1 text-lg font-bold text-text-primary\">\n {loan.emiPerLakh != null ? formatINRCompact(loan.emiPerLakh) : '—'}\n </div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <CalendarClock className=\"h-3.5 w-3.5\" />\n Max Tenure\n </div>\n <div className=\"mt-1 text-lg font-bold text-text-primary\">{loan.maxTenure} yrs</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"text-xs text-text-secondary\">Max Amount</div>\n <div className=\"mt-1 text-sm font-semibold text-text-primary\">{formatINRCompact(loan.maxAmount)}</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"text-xs text-text-secondary\">Processing Fee</div>\n <div className=\"mt-1 text-sm font-semibold text-text-primary\">{loan.processingFee ?? '—'}</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"text-xs text-text-secondary\">Prepayment</div>\n <div\n className={cn(\n 'mt-1 text-sm font-semibold',\n loan.prepaymentCharges === 'None' ? 'text-status-success-text' : 'text-text-primary'\n )}\n >\n {loan.prepaymentCharges ?? '—'}\n </div>\n </div>\n </div>\n </GlassCard>\n\n {features.length > 0 && (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Features</h2>\n <ul className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n {features.map((feature, i) => (\n <li key={i} className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <CheckCircle className=\"h-4 w-4 shrink-0 text-status-success-text\" />\n {feature}\n </li>\n ))}\n </ul>\n </GlassCard>\n )}\n </div>\n\n {/* Apply card */}\n <div className=\"space-y-6\">\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <h3 className=\"mb-2 text-base font-semibold text-text-primary\">Ready to apply?</h3>\n <p className=\"mb-4 text-sm text-text-secondary\">\n Applications are handled directly with {loan.bankName} through HousingVista Messages. Start an enquiry and\n the bank will guide you through eligibility and paperwork.\n </p>\n <Button\n type=\"button\"\n variant=\"default\"\n className=\"w-full justify-center\"\n onClick={() => setContactOpen(true)}\n >\n Apply Now\n </Button>\n </GlassCard>\n </div>\n </div>\n\n <ContactOwnerDialog\n open={contactOpen}\n onOpenChange={setContactOpen}\n entityId={loan.id}\n entityType=\"housingvista-home-loan\"\n title={loan.bankName}\n pagePath={location.pathname}\n heading={`Apply with ${loan.bankName}`}\n description={`Start your application with ${loan.bankName}. Messages are saved and delivered in your inbox.`}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HomeLoanDetailPage.js","names":[],"sources":["../../../../src/housingvista/pages/finance/HomeLoanDetailPage.tsx"],"sourcesContent":["/**\n * HousingVista Home Loan Detail / Apply Page\n * Single loan offer backed by `housingvistaHomeLoanOffer(id)` — full terms plus\n * a live EMI summary for the offer's headline rate.\n *\n * \"Apply\" opens the real `ContactOwnerDialog` — a persisted conversation with\n * the bank. No fabricated approval; the EMI calculator stays for modelling.\n * @module housingvista\n */\n\nimport { useMemo, useState } from 'react';\nimport { useNavigate, useParams, useLocation } from 'react-router-dom';\nimport {\n ArrowLeft,\n Building2,\n Star,\n CheckCircle,\n Gift,\n Calculator,\n Percent,\n Wallet,\n CalendarClock,\n} from 'lucide-react';\nimport { Button, EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { Breadcrumbs, StatusBadge, EmptyState, LoadingSkeleton, ContactOwnerDialog } from '../../components';\nimport type { BreadcrumbItem } from '../../components';\nimport { useHomeLoanOffer } from '../../hooks';\nimport { cn, formatCurrency, formatINRCompact } from '../../utils/helpers';\nimport { useTrackPageView } from '../../hooks/useHousingVistaAnalytics';\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-4 w-4', i < Math.floor(rating) ? 'fill-current' : 'fill-none text-text-secondary/30')}\n />\n ))}\n </div>\n );\n}\n\nexport function HomeLoanDetailPage() {\n const { id } = useParams<{ id: string }>();\n\n useTrackPageView('housingvista.home_loan.viewed', id);\n const navigate = useNavigate();\n const location = useLocation();\n const { data: loan, loading } = useHomeLoanOffer(id);\n\n // Model a representative loan against the offer's headline rate so the borrower\n // can see the real monthly cost before enquiring.\n const [amount, setAmount] = useState(500000);\n const [tenure, setTenure] = useState(20);\n const [contactOpen, setContactOpen] = useState(false);\n\n const rate = loan?.interestRate ?? 0;\n const emi = useMemo(() => calculateEMI(amount, rate, tenure), [amount, rate, tenure]);\n const totalPayment = emi * tenure * 12;\n const totalInterest = totalPayment - amount;\n\n if (loading) {\n return (\n <div className=\"p-6\">\n <LoadingSkeleton variant=\"detail\" />\n </div>\n );\n }\n\n if (!loan) {\n return (\n <div className=\"p-6\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<Building2 className=\"h-12 w-12\" />}\n title=\"Loan Offer Not Found\"\n description=\"The loan offer you're looking for doesn't exist or is no longer available.\"\n action={\n <button\n onClick={() => navigate('../home-loans')}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Home Loans\n </button>\n }\n />\n </div>\n );\n }\n\n const features = loan.features ?? [];\n const breadcrumbs: BreadcrumbItem[] = [{ label: 'Home Loans', href: '../' }, { label: loan.bankName }];\n\n return (\n <div className=\"flex flex-col gap-6 p-6\">\n <Breadcrumbs items={breadcrumbs} />\n\n {/* Header */}\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"flex items-start gap-4\">\n <div className=\"flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <Building2 className=\"h-6 w-6\" />\n </div>\n <div>\n <button\n onClick={() => navigate('../home-loans')}\n className=\"mb-2 inline-flex items-center gap-2 rounded-md px-2 py-1 text-sm text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Home Loans\n </button>\n <h1 className=\"text-2xl font-semibold text-text-primary\">{loan.bankName}</h1>\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n {loan.rating != null && (\n <span className=\"inline-flex items-center gap-1.5\">\n <RatingStars rating={loan.rating} />\n <span className=\"text-sm text-text-secondary\">{loan.rating}</span>\n </span>\n )}\n {loan.specialOffer && <StatusBadge label=\"Special Offer\" variant=\"warning\" />}\n </div>\n </div>\n </div>\n <Button type=\"button\" variant=\"default\" onClick={() => setContactOpen(true)}>\n Apply Now\n </Button>\n </div>\n\n <PagePurpose className=\"max-w-3xl\">\n The full terms of this offer with a live EMI estimate at the bank's headline rate. Model your loan amount and\n tenure to see the real monthly cost, then apply to connect with {loan.bankName} through Messages.\n </PagePurpose>\n\n {loan.specialOffer && (\n <div className=\"flex items-center gap-2 rounded-lg bg-status-warning-bg-subtle p-3 text-sm text-status-warning-text\">\n <Gift className=\"h-4 w-4 shrink-0\" />\n {loan.specialOffer}\n </div>\n )}\n\n {/* EMI summary — 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 Estimate at {loan.interestRate}%</h2>\n </div>\n <div className=\"grid gap-6 md:grid-cols-2\">\n <div className=\"space-y-5\">\n <div>\n <div className=\"mb-2 flex items-center justify-between\">\n <label className=\"text-sm font-medium text-text-primary\">Loan Amount</label>\n <span className=\"text-sm font-semibold text-text-primary\">{formatCurrency(amount)}</span>\n </div>\n <input\n type=\"range\"\n min={50000}\n max={Math.max(loan.maxAmount, 100000)}\n step={10000}\n value={Math.min(amount, loan.maxAmount)}\n onChange={(e) => setAmount(Number(e.target.value))}\n aria-label=\"Loan amount\"\n className={SLIDER_CLASS}\n />\n <div className=\"mt-1 flex justify-between text-xs text-text-secondary\">\n <span>₹50K</span>\n <span>Max {formatINRCompact(loan.maxAmount)}</span>\n </div>\n </div>\n <div>\n <div className=\"mb-2 flex items-center justify-between\">\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={loan.maxTenure}\n step={1}\n value={Math.min(tenure, loan.maxTenure)}\n onChange={(e) => setTenure(Number(e.target.value))}\n aria-label=\"Tenure in years\"\n className={SLIDER_CLASS}\n />\n <div className=\"mt-1 flex justify-between text-xs text-text-secondary\">\n <span>1 yr</span>\n <span>Max {loan.maxTenure} yrs</span>\n </div>\n </div>\n </div>\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 </div>\n </div>\n </EmphasisPanel>\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Terms */}\n <div className=\"space-y-6 lg:col-span-2\">\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Loan Terms</h2>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <Percent className=\"h-3.5 w-3.5\" />\n Interest Rate\n </div>\n <div className=\"mt-1 text-lg font-bold text-text-primary\">{loan.interestRate}%</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <Wallet className=\"h-3.5 w-3.5\" />\n EMI / Lakh\n </div>\n <div className=\"mt-1 text-lg font-bold text-text-primary\">\n {loan.emiPerLakh != null ? formatINRCompact(loan.emiPerLakh) : '—'}\n </div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <CalendarClock className=\"h-3.5 w-3.5\" />\n Max Tenure\n </div>\n <div className=\"mt-1 text-lg font-bold text-text-primary\">{loan.maxTenure} yrs</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"text-xs text-text-secondary\">Max Amount</div>\n <div className=\"mt-1 text-sm font-semibold text-text-primary\">{formatINRCompact(loan.maxAmount)}</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"text-xs text-text-secondary\">Processing Fee</div>\n <div className=\"mt-1 text-sm font-semibold text-text-primary\">{loan.processingFee ?? '—'}</div>\n </div>\n <div className=\"rounded-lg bg-bg-sunken/50 p-4\">\n <div className=\"text-xs text-text-secondary\">Prepayment</div>\n <div\n className={cn(\n 'mt-1 text-sm font-semibold',\n loan.prepaymentCharges === 'None' ? 'text-status-success-text' : 'text-text-primary'\n )}\n >\n {loan.prepaymentCharges ?? '—'}\n </div>\n </div>\n </div>\n </GlassCard>\n\n {features.length > 0 && (\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Features</h2>\n <ul className=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n {features.map((feature, i) => (\n <li key={i} className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <CheckCircle className=\"h-4 w-4 shrink-0 text-status-success-text\" />\n {feature}\n </li>\n ))}\n </ul>\n </GlassCard>\n )}\n </div>\n\n {/* Apply card */}\n <div className=\"space-y-6\">\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-5\">\n <h3 className=\"mb-2 text-base font-semibold text-text-primary\">Ready to apply?</h3>\n <p className=\"mb-4 text-sm text-text-secondary\">\n Applications are handled directly with {loan.bankName} through HousingVista Messages. Start an enquiry and\n the bank will guide you through eligibility and paperwork.\n </p>\n <Button\n type=\"button\"\n variant=\"default\"\n className=\"w-full justify-center\"\n onClick={() => setContactOpen(true)}\n >\n Apply Now\n </Button>\n </GlassCard>\n </div>\n </div>\n\n <ContactOwnerDialog\n open={contactOpen}\n onOpenChange={setContactOpen}\n entityId={loan.id}\n entityType=\"housingvista-home-loan\"\n title={loan.bankName}\n pagePath={location.pathname}\n heading={`Apply with ${loan.bankName}`}\n description={`Start your application with ${loan.bankName}. Messages are saved and delivered in your inbox.`}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HomeLoansPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/finance/HomeLoansPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HomeLoansPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/finance/HomeLoansPage.tsx"],"names":[],"mappings":"AAoIA,wBAAgB,aAAa,gCA2N5B"}
|
|
@@ -3,294 +3,296 @@ import { PageLayout as r } from "../../components/PageLayout.js";
|
|
|
3
3
|
import { EmptyState as i } from "../../components/EmptyState.js";
|
|
4
4
|
import { FilterBar as a } from "../../components/FilterBar.js";
|
|
5
5
|
import { LoadingSkeleton as o } from "../../components/LoadingSkeleton.js";
|
|
6
|
-
import {
|
|
6
|
+
import { useTrackPageView as s } from "../../hooks/useHousingVistaAnalytics.js";
|
|
7
|
+
import { useHomeLoans as c } from "../../hooks/index.js";
|
|
7
8
|
import "../../components/index.js";
|
|
8
|
-
import { useServerPagination as
|
|
9
|
-
import { useMemo as
|
|
10
|
-
import { ArrowRight as
|
|
11
|
-
import { useNavigate as
|
|
12
|
-
import { Fragment as
|
|
13
|
-
import { EmphasisPanel as
|
|
9
|
+
import { useServerPagination as l } from "../../hooks/useServerPagination.js";
|
|
10
|
+
import { useMemo as u, useState as d } from "react";
|
|
11
|
+
import { ArrowRight as f, Building2 as p, Calculator as m, CheckCircle as h, Gift as g, Star as _ } from "lucide-react";
|
|
12
|
+
import { useNavigate as v } from "react-router-dom";
|
|
13
|
+
import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
14
|
+
import { EmphasisPanel as S, NextSteps as C, Pagination as w } from "@burdenoff/fe-libs/ui";
|
|
14
15
|
//#region src/housingvista/pages/finance/HomeLoansPage.tsx
|
|
15
|
-
var
|
|
16
|
-
function
|
|
16
|
+
var T = 9, E = "w-full accent-[var(--color-action-primary-bg)]";
|
|
17
|
+
function D(e, t, n) {
|
|
17
18
|
if (e <= 0 || t <= 0 || n <= 0) return 0;
|
|
18
19
|
let r = t / 12 / 100, i = n * 12, a = e * r * (1 + r) ** +i / ((1 + r) ** +i - 1);
|
|
19
20
|
return Math.round(a);
|
|
20
21
|
}
|
|
21
|
-
function
|
|
22
|
-
return /* @__PURE__ */
|
|
22
|
+
function O({ rating: t }) {
|
|
23
|
+
return /* @__PURE__ */ b("div", {
|
|
23
24
|
className: "flex items-center gap-0.5 text-status-warning-text",
|
|
24
|
-
children: Array.from({ length: 5 }).map((n, r) => /* @__PURE__ */
|
|
25
|
+
children: Array.from({ length: 5 }).map((n, r) => /* @__PURE__ */ b(_, { className: e("h-3 w-3", r < Math.floor(t) ? "fill-current" : "fill-none text-text-secondary/30") }, r))
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
|
-
function
|
|
28
|
-
let r =
|
|
29
|
-
return /* @__PURE__ */
|
|
28
|
+
function k({ loan: t }) {
|
|
29
|
+
let r = v();
|
|
30
|
+
return /* @__PURE__ */ x("div", {
|
|
30
31
|
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",
|
|
31
32
|
children: [
|
|
32
|
-
/* @__PURE__ */
|
|
33
|
+
/* @__PURE__ */ x("div", {
|
|
33
34
|
className: "mb-4 flex items-start justify-between gap-3",
|
|
34
|
-
children: [/* @__PURE__ */
|
|
35
|
+
children: [/* @__PURE__ */ x("div", {
|
|
35
36
|
className: "flex items-center gap-3",
|
|
36
|
-
children: [/* @__PURE__ */
|
|
37
|
+
children: [/* @__PURE__ */ b("div", {
|
|
37
38
|
className: "flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-accent-blue-subtle",
|
|
38
|
-
children: /* @__PURE__ */
|
|
39
|
-
}), /* @__PURE__ */
|
|
39
|
+
children: /* @__PURE__ */ b(p, { className: "h-6 w-6 text-accent-blue" })
|
|
40
|
+
}), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h3", {
|
|
40
41
|
className: "text-sm font-semibold text-text-primary",
|
|
41
42
|
children: t.bankName
|
|
42
|
-
}), /* @__PURE__ */
|
|
43
|
+
}), /* @__PURE__ */ x("div", {
|
|
43
44
|
className: "flex items-center gap-1.5 mt-0.5",
|
|
44
|
-
children: [/* @__PURE__ */
|
|
45
|
+
children: [/* @__PURE__ */ b(O, { rating: t.rating }), /* @__PURE__ */ b("span", {
|
|
45
46
|
className: "text-xs text-text-secondary",
|
|
46
47
|
children: t.rating
|
|
47
48
|
})]
|
|
48
49
|
})] })]
|
|
49
|
-
}), t.specialOffer && /* @__PURE__ */
|
|
50
|
+
}), t.specialOffer && /* @__PURE__ */ x("span", {
|
|
50
51
|
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",
|
|
51
|
-
children: [/* @__PURE__ */
|
|
52
|
+
children: [/* @__PURE__ */ b(g, { className: "h-3 w-3" }), "Offer"]
|
|
52
53
|
})]
|
|
53
54
|
}),
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ x("div", {
|
|
55
56
|
className: "mb-4 grid grid-cols-2 gap-3",
|
|
56
57
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ x("div", {
|
|
58
59
|
className: "rounded-md bg-bg-sunken/50 p-2.5",
|
|
59
|
-
children: [/* @__PURE__ */
|
|
60
|
+
children: [/* @__PURE__ */ b("p", {
|
|
60
61
|
className: "text-xs text-text-secondary",
|
|
61
62
|
children: "Interest Rate"
|
|
62
|
-
}), /* @__PURE__ */
|
|
63
|
+
}), /* @__PURE__ */ x("p", {
|
|
63
64
|
className: "text-lg font-bold text-text-primary",
|
|
64
65
|
children: [t.interestRate, "%"]
|
|
65
66
|
})]
|
|
66
67
|
}),
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
+
/* @__PURE__ */ x("div", {
|
|
68
69
|
className: "rounded-md bg-bg-sunken/50 p-2.5",
|
|
69
|
-
children: [/* @__PURE__ */
|
|
70
|
+
children: [/* @__PURE__ */ b("p", {
|
|
70
71
|
className: "text-xs text-text-secondary",
|
|
71
72
|
children: "EMI / Lakh"
|
|
72
|
-
}), /* @__PURE__ */
|
|
73
|
+
}), /* @__PURE__ */ b("p", {
|
|
73
74
|
className: "text-lg font-bold text-text-primary",
|
|
74
75
|
children: n(t.emiPerLakh)
|
|
75
76
|
})]
|
|
76
77
|
}),
|
|
77
|
-
/* @__PURE__ */
|
|
78
|
+
/* @__PURE__ */ x("div", {
|
|
78
79
|
className: "rounded-md bg-bg-sunken/50 p-2.5",
|
|
79
|
-
children: [/* @__PURE__ */
|
|
80
|
+
children: [/* @__PURE__ */ b("p", {
|
|
80
81
|
className: "text-xs text-text-secondary",
|
|
81
82
|
children: "Max Tenure"
|
|
82
|
-
}), /* @__PURE__ */
|
|
83
|
+
}), /* @__PURE__ */ x("p", {
|
|
83
84
|
className: "text-sm font-semibold text-text-primary",
|
|
84
85
|
children: [t.maxTenure, " years"]
|
|
85
86
|
})]
|
|
86
87
|
}),
|
|
87
|
-
/* @__PURE__ */
|
|
88
|
+
/* @__PURE__ */ x("div", {
|
|
88
89
|
className: "rounded-md bg-bg-sunken/50 p-2.5",
|
|
89
|
-
children: [/* @__PURE__ */
|
|
90
|
+
children: [/* @__PURE__ */ b("p", {
|
|
90
91
|
className: "text-xs text-text-secondary",
|
|
91
92
|
children: "Max Amount"
|
|
92
|
-
}), /* @__PURE__ */
|
|
93
|
+
}), /* @__PURE__ */ b("p", {
|
|
93
94
|
className: "text-sm font-semibold text-text-primary",
|
|
94
95
|
children: n(t.maxAmount)
|
|
95
96
|
})]
|
|
96
97
|
})
|
|
97
98
|
]
|
|
98
99
|
}),
|
|
99
|
-
/* @__PURE__ */
|
|
100
|
+
/* @__PURE__ */ x("div", {
|
|
100
101
|
className: "mb-3 flex items-center justify-between text-xs",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
102
|
+
children: [/* @__PURE__ */ b("span", {
|
|
102
103
|
className: "text-text-secondary",
|
|
103
104
|
children: "Processing Fee"
|
|
104
|
-
}), /* @__PURE__ */
|
|
105
|
+
}), /* @__PURE__ */ b("span", {
|
|
105
106
|
className: "font-medium text-text-primary",
|
|
106
107
|
children: t.processingFee
|
|
107
108
|
})]
|
|
108
109
|
}),
|
|
109
|
-
/* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ x("div", {
|
|
110
111
|
className: "mb-3 flex items-center justify-between text-xs",
|
|
111
|
-
children: [/* @__PURE__ */
|
|
112
|
+
children: [/* @__PURE__ */ b("span", {
|
|
112
113
|
className: "text-text-secondary",
|
|
113
114
|
children: "Prepayment Charges"
|
|
114
|
-
}), /* @__PURE__ */
|
|
115
|
+
}), /* @__PURE__ */ b("span", {
|
|
115
116
|
className: e("font-medium", t.prepaymentCharges === "None" ? "text-status-success-text" : "text-text-primary"),
|
|
116
117
|
children: t.prepaymentCharges
|
|
117
118
|
})]
|
|
118
119
|
}),
|
|
119
|
-
t.specialOffer && /* @__PURE__ */
|
|
120
|
+
t.specialOffer && /* @__PURE__ */ b("div", {
|
|
120
121
|
className: "mb-3 rounded-md bg-status-warning-bg-subtle p-2.5 text-xs text-status-warning-text",
|
|
121
122
|
children: t.specialOffer
|
|
122
123
|
}),
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
+
/* @__PURE__ */ b("div", {
|
|
124
125
|
className: "mb-4 space-y-1.5",
|
|
125
|
-
children: t.features.map((e, t) => /* @__PURE__ */
|
|
126
|
+
children: t.features.map((e, t) => /* @__PURE__ */ x("div", {
|
|
126
127
|
className: "flex items-center gap-1.5 text-xs text-text-secondary",
|
|
127
|
-
children: [/* @__PURE__ */
|
|
128
|
+
children: [/* @__PURE__ */ b(h, { className: "h-3 w-3 shrink-0 text-status-success-text" }), e]
|
|
128
129
|
}, t))
|
|
129
130
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ x("button", {
|
|
131
132
|
onClick: () => r(`../home-loans/${t.id}/apply`),
|
|
132
133
|
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",
|
|
133
|
-
children: ["Apply Now", /* @__PURE__ */
|
|
134
|
+
children: ["Apply Now", /* @__PURE__ */ b(f, { className: "h-3.5 w-3.5" })]
|
|
134
135
|
})
|
|
135
136
|
]
|
|
136
137
|
});
|
|
137
138
|
}
|
|
138
|
-
function
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
function A() {
|
|
140
|
+
s("housingvista.home_loan.viewed");
|
|
141
|
+
let e = v(), n = l(T), { data: f, loading: h } = c(n.pagination), [g, _] = d(""), O = u(() => {
|
|
142
|
+
let e = g.trim().toLowerCase();
|
|
143
|
+
return e ? f.filter((t) => t.bankName.toLowerCase().includes(e) || t.features.some((t) => t.toLowerCase().includes(e)) || (t.specialOffer ?? "").toLowerCase().includes(e)) : f;
|
|
144
|
+
}, [f, g]), A = f.length >= n.pageSize, [j, M] = d(5e6), [N, P] = d(20), [F, I] = d(6.75), L = u(() => D(j, F, N), [
|
|
145
|
+
j,
|
|
146
|
+
F,
|
|
147
|
+
N
|
|
148
|
+
]), R = L * N * 12, z = R - j;
|
|
149
|
+
return /* @__PURE__ */ x(r, {
|
|
148
150
|
title: "Home Loans",
|
|
149
151
|
description: "Compare rates, calculate EMI, and apply for home loans",
|
|
150
152
|
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.",
|
|
151
153
|
children: [
|
|
152
|
-
/* @__PURE__ */
|
|
154
|
+
/* @__PURE__ */ x(S, {
|
|
153
155
|
className: "p-5",
|
|
154
|
-
children: [/* @__PURE__ */
|
|
156
|
+
children: [/* @__PURE__ */ x("div", {
|
|
155
157
|
className: "mb-4 flex items-center gap-2",
|
|
156
|
-
children: [/* @__PURE__ */
|
|
158
|
+
children: [/* @__PURE__ */ b(m, { className: "h-5 w-5 text-text-secondary" }), /* @__PURE__ */ b("h2", {
|
|
157
159
|
className: "text-lg font-semibold text-text-primary",
|
|
158
160
|
children: "EMI Calculator"
|
|
159
161
|
})]
|
|
160
|
-
}), /* @__PURE__ */
|
|
162
|
+
}), /* @__PURE__ */ x("div", {
|
|
161
163
|
className: "grid gap-6 md:grid-cols-2",
|
|
162
|
-
children: [/* @__PURE__ */
|
|
164
|
+
children: [/* @__PURE__ */ x("div", {
|
|
163
165
|
className: "space-y-5",
|
|
164
166
|
children: [
|
|
165
|
-
/* @__PURE__ */
|
|
166
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ x("div", { children: [
|
|
168
|
+
/* @__PURE__ */ x("div", {
|
|
167
169
|
className: "flex items-center justify-between mb-2",
|
|
168
|
-
children: [/* @__PURE__ */
|
|
170
|
+
children: [/* @__PURE__ */ b("label", {
|
|
169
171
|
className: "text-sm font-medium text-text-primary",
|
|
170
172
|
children: "Loan Amount"
|
|
171
|
-
}), /* @__PURE__ */
|
|
173
|
+
}), /* @__PURE__ */ b("span", {
|
|
172
174
|
className: "text-sm font-semibold text-text-primary",
|
|
173
|
-
children: t(
|
|
175
|
+
children: t(j)
|
|
174
176
|
})]
|
|
175
177
|
}),
|
|
176
|
-
/* @__PURE__ */
|
|
178
|
+
/* @__PURE__ */ b("input", {
|
|
177
179
|
type: "range",
|
|
178
180
|
min: 1e5,
|
|
179
181
|
max: 5e7,
|
|
180
182
|
step: 1e5,
|
|
181
|
-
value:
|
|
182
|
-
onChange: (e) =>
|
|
183
|
+
value: j,
|
|
184
|
+
onChange: (e) => M(Number(e.target.value)),
|
|
183
185
|
"aria-label": "Loan amount",
|
|
184
|
-
className:
|
|
186
|
+
className: E
|
|
185
187
|
}),
|
|
186
|
-
/* @__PURE__ */
|
|
188
|
+
/* @__PURE__ */ x("div", {
|
|
187
189
|
className: "flex justify-between text-xs text-text-secondary mt-1",
|
|
188
|
-
children: [/* @__PURE__ */
|
|
190
|
+
children: [/* @__PURE__ */ b("span", { children: "₹1 L" }), /* @__PURE__ */ b("span", { children: "₹5 Cr" })]
|
|
189
191
|
})
|
|
190
192
|
] }),
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
-
/* @__PURE__ */
|
|
193
|
+
/* @__PURE__ */ x("div", { children: [
|
|
194
|
+
/* @__PURE__ */ x("div", {
|
|
193
195
|
className: "flex items-center justify-between mb-2",
|
|
194
|
-
children: [/* @__PURE__ */
|
|
196
|
+
children: [/* @__PURE__ */ b("label", {
|
|
195
197
|
className: "text-sm font-medium text-text-primary",
|
|
196
198
|
children: "Tenure (years)"
|
|
197
|
-
}), /* @__PURE__ */
|
|
199
|
+
}), /* @__PURE__ */ x("span", {
|
|
198
200
|
className: "text-sm font-semibold text-text-primary",
|
|
199
|
-
children: [
|
|
201
|
+
children: [N, " years"]
|
|
200
202
|
})]
|
|
201
203
|
}),
|
|
202
|
-
/* @__PURE__ */
|
|
204
|
+
/* @__PURE__ */ b("input", {
|
|
203
205
|
type: "range",
|
|
204
206
|
min: 1,
|
|
205
207
|
max: 30,
|
|
206
208
|
step: 1,
|
|
207
|
-
value:
|
|
208
|
-
onChange: (e) =>
|
|
209
|
-
className:
|
|
209
|
+
value: N,
|
|
210
|
+
onChange: (e) => P(Number(e.target.value)),
|
|
211
|
+
className: E
|
|
210
212
|
}),
|
|
211
|
-
/* @__PURE__ */
|
|
213
|
+
/* @__PURE__ */ x("div", {
|
|
212
214
|
className: "flex justify-between text-xs text-text-secondary mt-1",
|
|
213
|
-
children: [/* @__PURE__ */
|
|
215
|
+
children: [/* @__PURE__ */ b("span", { children: "1 yr" }), /* @__PURE__ */ b("span", { children: "30 yrs" })]
|
|
214
216
|
})
|
|
215
217
|
] }),
|
|
216
|
-
/* @__PURE__ */
|
|
217
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ x("div", { children: [
|
|
219
|
+
/* @__PURE__ */ x("div", {
|
|
218
220
|
className: "flex items-center justify-between mb-2",
|
|
219
|
-
children: [/* @__PURE__ */
|
|
221
|
+
children: [/* @__PURE__ */ b("label", {
|
|
220
222
|
className: "text-sm font-medium text-text-primary",
|
|
221
223
|
children: "Interest Rate (%)"
|
|
222
|
-
}), /* @__PURE__ */
|
|
224
|
+
}), /* @__PURE__ */ x("span", {
|
|
223
225
|
className: "text-sm font-semibold text-text-primary",
|
|
224
|
-
children: [
|
|
226
|
+
children: [F, "%"]
|
|
225
227
|
})]
|
|
226
228
|
}),
|
|
227
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ b("input", {
|
|
228
230
|
type: "range",
|
|
229
231
|
min: 3,
|
|
230
232
|
max: 15,
|
|
231
233
|
step: .05,
|
|
232
|
-
value:
|
|
233
|
-
onChange: (e) =>
|
|
234
|
-
className:
|
|
234
|
+
value: F,
|
|
235
|
+
onChange: (e) => I(Number(e.target.value)),
|
|
236
|
+
className: E
|
|
235
237
|
}),
|
|
236
|
-
/* @__PURE__ */
|
|
238
|
+
/* @__PURE__ */ x("div", {
|
|
237
239
|
className: "flex justify-between text-xs text-text-secondary mt-1",
|
|
238
|
-
children: [/* @__PURE__ */
|
|
240
|
+
children: [/* @__PURE__ */ b("span", { children: "3%" }), /* @__PURE__ */ b("span", { children: "15%" })]
|
|
239
241
|
})
|
|
240
242
|
] })
|
|
241
243
|
]
|
|
242
|
-
}), /* @__PURE__ */
|
|
244
|
+
}), /* @__PURE__ */ x("div", {
|
|
243
245
|
className: "flex flex-col items-center justify-center rounded-lg bg-bg-sunken/50 p-6",
|
|
244
246
|
children: [
|
|
245
|
-
/* @__PURE__ */
|
|
247
|
+
/* @__PURE__ */ b("p", {
|
|
246
248
|
className: "text-sm text-text-secondary",
|
|
247
249
|
children: "Monthly EMI"
|
|
248
250
|
}),
|
|
249
|
-
/* @__PURE__ */
|
|
251
|
+
/* @__PURE__ */ b("p", {
|
|
250
252
|
className: "my-2 text-4xl font-bold text-text-primary",
|
|
251
|
-
children: t(
|
|
253
|
+
children: t(L)
|
|
252
254
|
}),
|
|
253
|
-
/* @__PURE__ */
|
|
255
|
+
/* @__PURE__ */ x("div", {
|
|
254
256
|
className: "mt-4 grid w-full grid-cols-2 gap-4",
|
|
255
|
-
children: [/* @__PURE__ */
|
|
257
|
+
children: [/* @__PURE__ */ x("div", {
|
|
256
258
|
className: "text-center",
|
|
257
|
-
children: [/* @__PURE__ */
|
|
259
|
+
children: [/* @__PURE__ */ b("p", {
|
|
258
260
|
className: "text-xs text-text-secondary",
|
|
259
261
|
children: "Total Payment"
|
|
260
|
-
}), /* @__PURE__ */
|
|
262
|
+
}), /* @__PURE__ */ b("p", {
|
|
261
263
|
className: "text-sm font-semibold text-text-primary",
|
|
262
|
-
children: t(
|
|
264
|
+
children: t(R)
|
|
263
265
|
})]
|
|
264
|
-
}), /* @__PURE__ */
|
|
266
|
+
}), /* @__PURE__ */ x("div", {
|
|
265
267
|
className: "text-center",
|
|
266
|
-
children: [/* @__PURE__ */
|
|
268
|
+
children: [/* @__PURE__ */ b("p", {
|
|
267
269
|
className: "text-xs text-text-secondary",
|
|
268
270
|
children: "Total Interest"
|
|
269
|
-
}), /* @__PURE__ */
|
|
271
|
+
}), /* @__PURE__ */ b("p", {
|
|
270
272
|
className: "text-sm font-semibold text-status-error-text",
|
|
271
|
-
children: t(
|
|
273
|
+
children: t(z)
|
|
272
274
|
})]
|
|
273
275
|
})]
|
|
274
276
|
}),
|
|
275
|
-
/* @__PURE__ */
|
|
277
|
+
/* @__PURE__ */ x("div", {
|
|
276
278
|
className: "mt-4 w-full",
|
|
277
|
-
children: [/* @__PURE__ */
|
|
279
|
+
children: [/* @__PURE__ */ x("div", {
|
|
278
280
|
className: "flex h-3 w-full overflow-hidden rounded-full",
|
|
279
|
-
children: [/* @__PURE__ */
|
|
281
|
+
children: [/* @__PURE__ */ b("div", {
|
|
280
282
|
className: "bg-chart-1 transition-all",
|
|
281
|
-
style: { width: `${
|
|
282
|
-
}), /* @__PURE__ */
|
|
283
|
+
style: { width: `${j / R * 100}%` }
|
|
284
|
+
}), /* @__PURE__ */ b("div", {
|
|
283
285
|
className: "bg-chart-negative transition-all",
|
|
284
|
-
style: { width: `${
|
|
286
|
+
style: { width: `${z / R * 100}%` }
|
|
285
287
|
})]
|
|
286
|
-
}), /* @__PURE__ */
|
|
288
|
+
}), /* @__PURE__ */ x("div", {
|
|
287
289
|
className: "mt-1.5 flex justify-between text-xs text-text-secondary",
|
|
288
|
-
children: [/* @__PURE__ */
|
|
290
|
+
children: [/* @__PURE__ */ x("span", {
|
|
289
291
|
className: "flex items-center gap-1",
|
|
290
|
-
children: [/* @__PURE__ */
|
|
291
|
-
}), /* @__PURE__ */
|
|
292
|
+
children: [/* @__PURE__ */ b("span", { className: "h-2 w-2 rounded-full bg-chart-1" }), " Principal"]
|
|
293
|
+
}), /* @__PURE__ */ x("span", {
|
|
292
294
|
className: "flex items-center gap-1",
|
|
293
|
-
children: [/* @__PURE__ */
|
|
295
|
+
children: [/* @__PURE__ */ b("span", { className: "h-2 w-2 rounded-full bg-chart-negative" }), " Interest"]
|
|
294
296
|
})]
|
|
295
297
|
})]
|
|
296
298
|
})
|
|
@@ -298,7 +300,7 @@ function k() {
|
|
|
298
300
|
})]
|
|
299
301
|
})]
|
|
300
302
|
}),
|
|
301
|
-
/* @__PURE__ */
|
|
303
|
+
/* @__PURE__ */ b(C, {
|
|
302
304
|
storageKey: "housingvista-home-loans",
|
|
303
305
|
steps: [
|
|
304
306
|
{
|
|
@@ -306,7 +308,7 @@ function k() {
|
|
|
306
308
|
label: "Apply to the best-rated offer",
|
|
307
309
|
description: "Start an application with a top partner bank.",
|
|
308
310
|
onClick: () => {
|
|
309
|
-
let t = [...
|
|
311
|
+
let t = [...f].sort((e, t) => t.rating - e.rating)[0];
|
|
310
312
|
t && e(`../home-loans/${t.id}/apply`);
|
|
311
313
|
}
|
|
312
314
|
},
|
|
@@ -324,36 +326,36 @@ function k() {
|
|
|
324
326
|
}
|
|
325
327
|
]
|
|
326
328
|
}),
|
|
327
|
-
/* @__PURE__ */
|
|
329
|
+
/* @__PURE__ */ x("div", {
|
|
328
330
|
className: "space-y-4",
|
|
329
331
|
children: [
|
|
330
|
-
/* @__PURE__ */
|
|
332
|
+
/* @__PURE__ */ b("h2", {
|
|
331
333
|
className: "text-lg font-semibold text-text-primary",
|
|
332
334
|
children: "Available Loan Offers"
|
|
333
335
|
}),
|
|
334
|
-
/* @__PURE__ */
|
|
335
|
-
searchValue:
|
|
336
|
-
onSearchChange:
|
|
336
|
+
/* @__PURE__ */ b(a, {
|
|
337
|
+
searchValue: g,
|
|
338
|
+
onSearchChange: _,
|
|
337
339
|
searchPlaceholder: "Search banks, features, offers on this page..."
|
|
338
340
|
}),
|
|
339
|
-
|
|
341
|
+
h ? /* @__PURE__ */ b(o, {
|
|
340
342
|
variant: "card",
|
|
341
343
|
count: 6
|
|
342
|
-
}) :
|
|
344
|
+
}) : O.length > 0 ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b("div", {
|
|
343
345
|
className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
344
|
-
children:
|
|
345
|
-
}), /* @__PURE__ */
|
|
346
|
+
children: O.map((e) => /* @__PURE__ */ b(k, { loan: e }, e.id))
|
|
347
|
+
}), /* @__PURE__ */ b(w, {
|
|
346
348
|
page: n.page,
|
|
347
349
|
pageSize: n.pageSize,
|
|
348
|
-
hasNextPage:
|
|
350
|
+
hasNextPage: A,
|
|
349
351
|
hasPreviousPage: n.page > 1,
|
|
350
352
|
onPageChange: n.setPage,
|
|
351
353
|
onPageSizeChange: n.setPageSize
|
|
352
|
-
})] }) : /* @__PURE__ */
|
|
353
|
-
illustration:
|
|
354
|
-
icon: /* @__PURE__ */
|
|
355
|
-
title:
|
|
356
|
-
description:
|
|
354
|
+
})] }) : /* @__PURE__ */ b(i, {
|
|
355
|
+
illustration: g ? "empty-search" : "empty-data",
|
|
356
|
+
icon: /* @__PURE__ */ b(p, { className: "h-12 w-12" }),
|
|
357
|
+
title: g ? "No matching loan offers" : "No loan offers available",
|
|
358
|
+
description: g ? "No offers on this page match your search. Clear the search or try another page." : "Check back later for new loan offers from our partner banks."
|
|
357
359
|
})
|
|
358
360
|
]
|
|
359
361
|
})
|
|
@@ -361,6 +363,6 @@ function k() {
|
|
|
361
363
|
});
|
|
362
364
|
}
|
|
363
365
|
//#endregion
|
|
364
|
-
export {
|
|
366
|
+
export { A as HomeLoansPage };
|
|
365
367
|
|
|
366
368
|
//# sourceMappingURL=HomeLoansPage.js.map
|