Compare commits

..

1 Commits

Author SHA1 Message Date
92a8e4f84e fix(deps): update dependency zod to v4
Some checks failed
Lint / Lint and Typecheck (push) Failing after 45s
Lint / Lint and Typecheck (pull_request) Failing after 46s
2025-07-12 00:03:38 +00:00
7 changed files with 7671 additions and 5173 deletions

View File

@@ -4,7 +4,7 @@ on:
pull_request: pull_request:
push: push:
branches: branches:
- "**" # matches every branch - '**' # matches every branch
jobs: jobs:
lint_and_typecheck: lint_and_typecheck:
@@ -15,17 +15,14 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: 22 node-version: 22
cache: "pnpm" cache: 'npm'
- name: Install dependencies - name: Install dependencies
run: pnpm install run: npm ci
- name: Run check - name: Run check
run: pnpm run check run: npm run check

View File

@@ -29,6 +29,7 @@ The projects code is structured using React/Next.js with TypeScript, focusing
The calculator models your FIRE journey in two phases: The calculator models your FIRE journey in two phases:
1. **Accumulation:** 1. **Accumulation:**
- Your starting capital is grown by your expected CAGR (~7% by default). - Your starting capital is grown by your expected CAGR (~7% by default).
- Monthly savings are added for each year until retirement. - Monthly savings are added for each year until retirement.
- Every variable can be adjusted live (capital, savings, age, growth, inflation, spending, target retirement). - Every variable can be adjusted live (capital, savings, age, growth, inflation, spending, target retirement).
@@ -57,11 +58,11 @@ To run locally:
``` ```
2. **Install dependencies** 2. **Install dependencies**
```bash ```bash
pnpm install npm install
``` ```
3. **Run the app** 3. **Run the app**
```bash ```bash
pnpm run dev npm run dev
``` ```
4. Visit [http://localhost:3000](http://localhost:3000) and unleash the fire. 4. Visit [http://localhost:3000](http://localhost:3000) and unleash the fire.

7628
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -29,29 +29,28 @@
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-hook-form": "^7.56.1", "react-hook-form": "^7.56.1",
"recharts": "^3.0.0", "recharts": "^2.15.3",
"tailwind-merge": "^3.2.0", "tailwind-merge": "^3.2.0",
"zod": "^4.0.0" "zod": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "3.3.1", "@eslint/eslintrc": "3.3.1",
"@tailwindcss/postcss": "4.1.11", "@tailwindcss/postcss": "4.1.11",
"@types/node": "22.16.3", "@types/node": "22.16.0",
"@types/react": "19.1.8", "@types/react": "19.1.8",
"@types/react-dom": "19.1.6", "@types/react-dom": "19.1.6",
"eslint": "9.31.0", "eslint": "9.30.1",
"eslint-config-next": "15.3.5", "eslint-config-next": "15.3.5",
"eslint-plugin-react-hooks": "^5.2.0",
"postcss": "8.5.6", "postcss": "8.5.6",
"prettier": "3.6.2", "prettier": "3.6.2",
"prettier-plugin-tailwindcss": "0.6.14", "prettier-plugin-tailwindcss": "0.6.13",
"tailwindcss": "4.1.11", "tailwindcss": "4.1.11",
"tw-animate-css": "1.3.5", "tw-animate-css": "1.3.5",
"typescript": "5.8.3", "typescript": "5.8.3",
"typescript-eslint": "8.36.0" "typescript-eslint": "8.35.1"
}, },
"ct3aMetadata": { "ct3aMetadata": {
"initVersion": "7.39.3" "initVersion": "7.39.3"
}, },
"packageManager": "pnpm@10.13.1" "packageManager": "npm@11.4.2"
} }

5070
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
ignoredBuiltDependencies:
- unrs-resolver
onlyBuiltDependencies:
- '@tailwindcss/oxide'
- sharp

View File

@@ -120,7 +120,7 @@ export default function FireCalculatorForm() {
const [showing4percent, setShowing4percent] = useState(false); const [showing4percent, setShowing4percent] = useState(false);
// Initialize form with default values // Initialize form with default values
const form = useForm<z.input<typeof formSchema>, undefined, FormValues>({ const form = useForm<FormValues>({
resolver: zodResolver(formSchema), resolver: zodResolver(formSchema),
defaultValues: { defaultValues: {
startingCapital: 50000, startingCapital: 50000,
@@ -258,18 +258,11 @@ export default function FireCalculatorForm() {
<Input <Input
placeholder="e.g., 10000" placeholder="e.g., 10000"
type="number" type="number"
value={field.value as number | string | undefined} {...field}
onChange={(e) => { onChange={(value) => {
field.onChange( field.onChange(value);
e.target.value === ""
? undefined
: Number(e.target.value),
);
void form.handleSubmit(onSubmit)(); void form.handleSubmit(onSubmit)();
}} }}
onBlur={field.onBlur}
name={field.name}
ref={field.ref}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
@@ -286,18 +279,11 @@ export default function FireCalculatorForm() {
<Input <Input
placeholder="e.g., 500" placeholder="e.g., 500"
type="number" type="number"
value={field.value as number | string | undefined} {...field}
onChange={(e) => { onChange={(value) => {
field.onChange( field.onChange(value);
e.target.value === ""
? undefined
: Number(e.target.value),
);
void form.handleSubmit(onSubmit)(); void form.handleSubmit(onSubmit)();
}} }}
onBlur={field.onBlur}
name={field.name}
ref={field.ref}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
@@ -314,18 +300,11 @@ export default function FireCalculatorForm() {
<Input <Input
placeholder="e.g., 30" placeholder="e.g., 30"
type="number" type="number"
value={field.value as number | string | undefined} {...field}
onChange={(e) => { onChange={(value) => {
field.onChange( field.onChange(value);
e.target.value === ""
? undefined
: Number(e.target.value),
);
void form.handleSubmit(onSubmit)(); void form.handleSubmit(onSubmit)();
}} }}
onBlur={field.onBlur}
name={field.name}
ref={field.ref}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
@@ -342,18 +321,11 @@ export default function FireCalculatorForm() {
<Input <Input
placeholder="e.g., 90" placeholder="e.g., 90"
type="number" type="number"
value={field.value as number | string | undefined} {...field}
onChange={(e) => { onChange={(value) => {
field.onChange( field.onChange(value);
e.target.value === ""
? undefined
: Number(e.target.value),
);
void form.handleSubmit(onSubmit)(); void form.handleSubmit(onSubmit)();
}} }}
onBlur={field.onBlur}
name={field.name}
ref={field.ref}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
@@ -371,18 +343,11 @@ export default function FireCalculatorForm() {
placeholder="e.g., 7" placeholder="e.g., 7"
type="number" type="number"
step="0.1" step="0.1"
value={field.value as number | string | undefined} {...field}
onChange={(e) => { onChange={(value) => {
field.onChange( field.onChange(value);
e.target.value === ""
? undefined
: Number(e.target.value),
);
void form.handleSubmit(onSubmit)(); void form.handleSubmit(onSubmit)();
}} }}
onBlur={field.onBlur}
name={field.name}
ref={field.ref}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
@@ -400,18 +365,11 @@ export default function FireCalculatorForm() {
placeholder="e.g., 2" placeholder="e.g., 2"
type="number" type="number"
step="0.1" step="0.1"
value={field.value as number | string | undefined} {...field}
onChange={(e) => { onChange={(value) => {
field.onChange( field.onChange(value);
e.target.value === ""
? undefined
: Number(e.target.value),
);
void form.handleSubmit(onSubmit)(); void form.handleSubmit(onSubmit)();
}} }}
onBlur={field.onBlur}
name={field.name}
ref={field.ref}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
@@ -430,18 +388,11 @@ export default function FireCalculatorForm() {
<Input <Input
placeholder="e.g., 2000" placeholder="e.g., 2000"
type="number" type="number"
value={field.value as number | string | undefined} {...field}
onChange={(e) => { onChange={(value) => {
field.onChange( field.onChange(value);
e.target.value === ""
? undefined
: Number(e.target.value),
);
void form.handleSubmit(onSubmit)(); void form.handleSubmit(onSubmit)();
}} }}
onBlur={field.onBlur}
name={field.name}
ref={field.ref}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
@@ -455,13 +406,11 @@ export default function FireCalculatorForm() {
name="retirementAge" name="retirementAge"
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>Retirement Age: {field.value}</FormLabel>
Retirement Age: {field.value as number}
</FormLabel>
<FormControl> <FormControl>
<Slider <Slider
name="retirementAge" name="retirementAge"
value={[field.value as number]} value={[field.value]}
min={25} min={25}
max={75} max={75}
step={1} step={1}
@@ -614,8 +563,8 @@ export default function FireCalculatorForm() {
<ReferenceLine <ReferenceLine
x={ x={
irlYear + irlYear +
(Number(form.getValues("retirementAge")) - (form.getValues("retirementAge") -
Number(form.getValues("currentAge"))) form.getValues("currentAge"))
} }
stroke="var(--primary)" stroke="var(--primary)"
strokeWidth={2} strokeWidth={2}
@@ -630,7 +579,7 @@ export default function FireCalculatorForm() {
x={ x={
irlYear + irlYear +
(result.retirementAge4percent - (result.retirementAge4percent -
Number(form.getValues("currentAge"))) form.getValues("currentAge"))
} }
stroke="var(--secondary)" stroke="var(--secondary)"
strokeWidth={1} strokeWidth={1}
@@ -693,8 +642,8 @@ export default function FireCalculatorForm() {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<p className="text-3xl font-bold"> <p className="text-3xl font-bold">
{Number(form.getValues("lifeExpectancy")) - {form.getValues("lifeExpectancy") -
Number(form.getValues("retirementAge"))} form.getValues("retirementAge")}
</p> </p>
</CardContent> </CardContent>
</Card> </Card>
@@ -725,7 +674,7 @@ export default function FireCalculatorForm() {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<p className="text-3xl font-bold"> <p className="text-3xl font-bold">
{Number(form.getValues("lifeExpectancy")) - {form.getValues("lifeExpectancy") -
(result.retirementAge4percent ?? 0)} (result.retirementAge4percent ?? 0)}
</p> </p>
</CardContent> </CardContent>