* feat(property): Layer 3 — Dream House Simulator Add /dream page with a four-phase simulation engine: Phase 1 — Save the down payment (uses current property equity) Phase 2 — Construction period (both loans running simultaneously) Phase 3 — Sell current house, apply proceeds to construction loan Phase 4 — Final state: just the construction loan remaining Inputs: dream cost, down payment %, construction loan rate/term, build duration, monthly savings, expected sale price. All pre-filled from existing property/loan data when available. Output: per-phase timeline cards, monthly cost bar chart, total interest, final payoff date, and a key levers section. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(plan): rename Dream House to Goal Planner at /plan - Route /dream → /plan - Nav label "Dream House" → "Goal Planner" - Template dream.html → plan.html - All user-facing labels generalised (construction loan → new loan, build duration → acquisition/build period, current property → current asset, dream house cost → new goal cost, etc.) - Empty state updated with generic copy and 🎯 icon Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(goals): merge Goal Planner into /goals as a second tab - /goals now has two tabs: "Committed goals" and "Goal Planner" - Goal creation only happens from the Planner tab (simulate first, then "Save as goal" → creates an uncommitted goal) - Commitment, deadline adjustment, and deletion stay on the Goals tab - Off-track goals show an "Adjust deadline →" button that pushes the deadline to the realistic date based on current savings rate - /plan and /dream both redirect to /goals?tab=planner (301) - "Goal Planner" nav link removed; plan.html kept for redirect compat - GoalsData gains Tab, PlanProperties, PlanLoans, HasPlanResult, PlanResult, PlanForm fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(goals): type-driven planner — Save for a purchase vs Sell & upgrade Goal Planner tab now opens with two goal type cards: 🛒 Save for a purchase — name, target, monthly savings, optional deadline. Shows time-to-reach at current rate, monthly needed to hit the deadline, and a feasibility banner. 🔄 Sell & upgrade — the full four-phase transition simulator (existing asset + loan → acquire new → sell old → payoff). Each type has its own focused form and result section. Selecting a type highlights the card and loads the matching form. Results include a "Save as goal" action that drops an uncommitted goal into the Goals tab. Also adds runPurchaseSim() and PurchaseSimResult model. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Gonçalo Rodrigues <guga@Goncalos-MacBook-Pro.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
2.7 KiB
Go
100 lines
2.7 KiB
Go
package main
|
|
|
|
import "time"
|
|
|
|
// DreamForm holds the raw user inputs echoed back to the template.
|
|
type DreamForm struct {
|
|
PropertyID string
|
|
LoanID string
|
|
DreamCostCents int64
|
|
DownPaymentPct float64
|
|
ConstructionRatePct float64
|
|
ConstructionTermYears int // what the user typed (years); converted to months internally
|
|
ConstructionTermMonths int // years * 12
|
|
BuildMonths int
|
|
MonthlySavingsCents int64
|
|
ExpectedSalePriceCents int64
|
|
}
|
|
|
|
// DreamSimResult is the computed output of one simulation run.
|
|
type DreamSimResult struct {
|
|
// Echoed inputs
|
|
Form DreamForm
|
|
|
|
// Current state (from selected property/loan)
|
|
CurrentProperty *PropertyView
|
|
CurrentLoan *LoanView
|
|
CurrentMonthlyCents int64
|
|
|
|
// Construction loan details
|
|
ConstructionLoanCents int64
|
|
ConstructionMonthly int64
|
|
|
|
// Phase 1 — save the down payment
|
|
DownPaymentCents int64
|
|
AlreadyHaveCents int64 // equity usable today
|
|
StillNeededCents int64
|
|
Phase1Months int
|
|
Phase1EndDate time.Time
|
|
|
|
// Phase 2 — construction (both loans running)
|
|
Phase2Months int
|
|
Phase2EndDate time.Time
|
|
Phase2MonthlyCents int64 // mortgage + construction EMI
|
|
ExistingBalanceAtSale int64 // mortgage balance at time of sale
|
|
ConstructionBalAtSale int64 // construction loan balance at time of sale
|
|
|
|
// Phase 3 — sell current house, pay down construction loan
|
|
SalePriceCents int64
|
|
MortgagePayoffCents int64
|
|
NetProceedsCents int64
|
|
RemainingBalanceCents int64 // construction loan after applying proceeds
|
|
|
|
// Phase 4 — just the construction loan
|
|
Phase4MonthlyCents int64
|
|
Phase4Months int
|
|
Phase4EndDate time.Time
|
|
|
|
// Totals
|
|
TotalMonths int
|
|
TotalYears int // TotalMonths / 12
|
|
TotalRemMonths int // TotalMonths % 12
|
|
FinalDate time.Time
|
|
TotalInterestCents int64
|
|
|
|
Warning string
|
|
}
|
|
|
|
// PurchaseSimResult is the computed output for a simple save-for-purchase goal.
|
|
type PurchaseSimResult struct {
|
|
Name string
|
|
TargetCents int64
|
|
MonthlySavingsCents int64
|
|
// At-current-savings projection
|
|
MonthsNeeded int
|
|
YearsNeeded int
|
|
RemMonths int
|
|
ReachDate time.Time
|
|
// Deadline projection (only set when a deadline was provided)
|
|
HasDeadline bool
|
|
DeadlineDate time.Time
|
|
DeadlineMonths int
|
|
MonthlyNeededForDeadline int64
|
|
Feasible bool // monthly savings >= monthly needed for deadline
|
|
}
|
|
|
|
// DreamData is passed to the dream.html template (kept for compat; redirect goes to /goals).
|
|
type DreamData struct {
|
|
UserID string
|
|
Email string
|
|
Title string
|
|
Route string
|
|
|
|
Properties []PropertyView
|
|
Loans []LoanView
|
|
|
|
HasResult bool
|
|
Result *DreamSimResult
|
|
Form DreamForm
|
|
}
|