attempt to add variable fixed epenses in onboaring
This commit is contained in:
@@ -16,6 +16,7 @@ type Step = 1 | 2 | 3 | 4 | 5 | 6;
|
|||||||
|
|
||||||
type IncomeType = "regular" | "irregular";
|
type IncomeType = "regular" | "irregular";
|
||||||
type BudgetConservatism = "tight" | "moderate" | "relaxed" | "custom";
|
type BudgetConservatism = "tight" | "moderate" | "relaxed" | "custom";
|
||||||
|
type FixedAmountMode = "fixed" | "estimated";
|
||||||
|
|
||||||
type VariableCat = {
|
type VariableCat = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -37,6 +38,7 @@ type FixedItem = {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
amountCents: number; // absolute amount
|
amountCents: number; // absolute amount
|
||||||
|
amountMode: FixedAmountMode;
|
||||||
priority: number;
|
priority: number;
|
||||||
dueOn: string; // yyyy-mm-dd
|
dueOn: string; // yyyy-mm-dd
|
||||||
frequency?: "one-time" | "weekly" | "biweekly" | "monthly";
|
frequency?: "one-time" | "weekly" | "biweekly" | "monthly";
|
||||||
@@ -139,6 +141,7 @@ export default function OnboardingPage() {
|
|||||||
setFixeds(
|
setFixeds(
|
||||||
s.fixeds.map((f: FixedItem) => ({
|
s.fixeds.map((f: FixedItem) => ({
|
||||||
...f,
|
...f,
|
||||||
|
amountMode: f.amountMode === "estimated" ? "estimated" : "fixed",
|
||||||
schedule: f.schedule ?? defaultSchedule(),
|
schedule: f.schedule ?? defaultSchedule(),
|
||||||
autoPayEnabled: !!f.autoPayEnabled,
|
autoPayEnabled: !!f.autoPayEnabled,
|
||||||
}))
|
}))
|
||||||
@@ -317,6 +320,7 @@ export default function OnboardingPage() {
|
|||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
name: "",
|
name: "",
|
||||||
amountCents: 0,
|
amountCents: 0,
|
||||||
|
amountMode: "fixed",
|
||||||
priority: list.length + 1,
|
priority: list.length + 1,
|
||||||
dueOn: getTodayInTimezone(userTimezone),
|
dueOn: getTodayInTimezone(userTimezone),
|
||||||
frequency: "monthly",
|
frequency: "monthly",
|
||||||
@@ -405,6 +409,8 @@ export default function OnboardingPage() {
|
|||||||
const name = f.name.trim();
|
const name = f.name.trim();
|
||||||
if (!name) continue; // skip empties just in case
|
if (!name) continue; // skip empties just in case
|
||||||
try {
|
try {
|
||||||
|
const amountMode = f.amountMode ?? "fixed";
|
||||||
|
const planAmountCents = Math.max(0, f.amountCents || 0);
|
||||||
const schedule = f.autoPayEnabled
|
const schedule = f.autoPayEnabled
|
||||||
? {
|
? {
|
||||||
frequency: "monthly" as const,
|
frequency: "monthly" as const,
|
||||||
@@ -420,8 +426,10 @@ export default function OnboardingPage() {
|
|||||||
|
|
||||||
const created = await fixedPlansApi.create({
|
const created = await fixedPlansApi.create({
|
||||||
name,
|
name,
|
||||||
totalCents: f.amountCents,
|
totalCents: planAmountCents,
|
||||||
fundedCents: 0,
|
fundedCents: 0,
|
||||||
|
amountMode,
|
||||||
|
estimatedCents: amountMode === "estimated" ? planAmountCents : null,
|
||||||
priority: i + 1,
|
priority: i + 1,
|
||||||
dueOn: dueOnISO,
|
dueOn: dueOnISO,
|
||||||
frequency: f.frequency,
|
frequency: f.frequency,
|
||||||
@@ -520,7 +528,11 @@ export default function OnboardingPage() {
|
|||||||
dashboardSnapshot.fixedPlans.map((p, i) => ({
|
dashboardSnapshot.fixedPlans.map((p, i) => ({
|
||||||
id: p.id,
|
id: p.id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
amountCents: p.totalCents,
|
amountCents:
|
||||||
|
(p as any).amountMode === "estimated"
|
||||||
|
? Number((p as any).estimatedCents ?? p.totalCents)
|
||||||
|
: p.totalCents,
|
||||||
|
amountMode: (p as any).amountMode === "estimated" ? "estimated" : "fixed",
|
||||||
priority: i + 1,
|
priority: i + 1,
|
||||||
dueOn: p.dueOn,
|
dueOn: p.dueOn,
|
||||||
autoPayEnabled: false,
|
autoPayEnabled: false,
|
||||||
@@ -969,8 +981,8 @@ export default function OnboardingPage() {
|
|||||||
<h2 className="section-title text-xl">Fixed Expenses</h2>
|
<h2 className="section-title text-xl">Fixed Expenses</h2>
|
||||||
<p className="muted text-sm">
|
<p className="muted text-sm">
|
||||||
{incomeType === "regular"
|
{incomeType === "regular"
|
||||||
? "Set amounts for recurring bills and expenses"
|
? "Set fixed or estimated amounts for recurring bills and expenses"
|
||||||
: "Set amounts for recurring bills and choose payment planning options"}
|
: "Set fixed or estimated amounts and choose payment planning options"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1007,6 +1019,18 @@ export default function OnboardingPage() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="fixed-expense-fields">
|
<div className="fixed-expense-fields">
|
||||||
|
<select
|
||||||
|
className="fixed-expense-select"
|
||||||
|
value={f.amountMode}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateFixed(f.id, {
|
||||||
|
amountMode: (e.target.value as FixedAmountMode) || "fixed",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<option value="fixed">Fixed</option>
|
||||||
|
<option value="estimated">Estimated</option>
|
||||||
|
</select>
|
||||||
<CurrencyInput
|
<CurrencyInput
|
||||||
className="fixed-expense-input"
|
className="fixed-expense-input"
|
||||||
valueCents={f.amountCents}
|
valueCents={f.amountCents}
|
||||||
@@ -1030,6 +1054,11 @@ export default function OnboardingPage() {
|
|||||||
<option value="monthly">Monthly</option>
|
<option value="monthly">Monthly</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
{f.amountMode === "estimated" && (
|
||||||
|
<div className="text-xs muted mt-2">
|
||||||
|
Estimated bills can be true-upped later in Settings by applying the actual amount.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<label className="fixed-expense-checkbox">
|
<label className="fixed-expense-checkbox">
|
||||||
<input
|
<input
|
||||||
@@ -1183,6 +1212,11 @@ export default function OnboardingPage() {
|
|||||||
<span className="review-item-meta">
|
<span className="review-item-meta">
|
||||||
Due {formatDateInTimezone(f.dueOn, userTimezone)}
|
Due {formatDateInTimezone(f.dueOn, userTimezone)}
|
||||||
</span>
|
</span>
|
||||||
|
{f.amountMode === "estimated" && (
|
||||||
|
<span className="review-item-badge">
|
||||||
|
Estimated bill
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
{f.autoPayEnabled && (
|
{f.autoPayEnabled && (
|
||||||
<span className="review-item-badge">
|
<span className="review-item-badge">
|
||||||
{incomeType === "irregular" ? "Payment plan" : "Auto-fund"}
|
{incomeType === "irregular" ? "Payment plan" : "Auto-fund"}
|
||||||
|
|||||||
Reference in New Issue
Block a user