@jjlmoya/utils-finance 1.40.0 → 1.41.0

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 (33) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +3 -2
  3. package/src/entries.ts +5 -1
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/tool_validation.test.ts +2 -2
  7. package/src/tool/savingsRate/bibliography.astro +11 -0
  8. package/src/tool/savingsRate/bibliography.ts +12 -0
  9. package/src/tool/savingsRate/component.astro +326 -0
  10. package/src/tool/savingsRate/content.ts +1877 -0
  11. package/src/tool/savingsRate/entry.ts +31 -0
  12. package/src/tool/savingsRate/i18n/de.ts +3 -0
  13. package/src/tool/savingsRate/i18n/en.ts +1 -0
  14. package/src/tool/savingsRate/i18n/es.ts +3 -0
  15. package/src/tool/savingsRate/i18n/fr.ts +3 -0
  16. package/src/tool/savingsRate/i18n/id.ts +3 -0
  17. package/src/tool/savingsRate/i18n/it.ts +3 -0
  18. package/src/tool/savingsRate/i18n/ja.ts +3 -0
  19. package/src/tool/savingsRate/i18n/ko.ts +3 -0
  20. package/src/tool/savingsRate/i18n/nl.ts +3 -0
  21. package/src/tool/savingsRate/i18n/pl.ts +3 -0
  22. package/src/tool/savingsRate/i18n/pt.ts +3 -0
  23. package/src/tool/savingsRate/i18n/ru.ts +3 -0
  24. package/src/tool/savingsRate/i18n/sv.ts +3 -0
  25. package/src/tool/savingsRate/i18n/tr.ts +3 -0
  26. package/src/tool/savingsRate/i18n/zh.ts +3 -0
  27. package/src/tool/savingsRate/index.ts +11 -0
  28. package/src/tool/savingsRate/logic.test.ts +87 -0
  29. package/src/tool/savingsRate/logic.ts +121 -0
  30. package/src/tool/savingsRate/savings-rate-calculator.css +575 -0
  31. package/src/tool/savingsRate/seo.astro +11 -0
  32. package/src/tool/savingsRate/ui.ts +48 -0
  33. package/src/tools.ts +2 -1
@@ -0,0 +1,575 @@
1
+ .savings-rate-tool {
2
+ --sr-ink: #20294d;
3
+ --sr-muted: #687392;
4
+ --sr-paper: #fffdf8;
5
+ --sr-panel: #f0f3ff;
6
+ --sr-line: #d7def2;
7
+ --sr-accent: #435ee8;
8
+ --sr-accent-dark: #2639a8;
9
+ --sr-warm: #f5b544;
10
+ --sr-coral: #f27d6d;
11
+ --sr-sky: #dfeaff;
12
+
13
+ width: 100%;
14
+ max-width: 72rem;
15
+ margin: 0 auto;
16
+ color: var(--sr-ink);
17
+ }
18
+
19
+ .savings-rate-tool *,
20
+ .savings-rate-tool *::before,
21
+ .savings-rate-tool *::after {
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ :global(.theme-dark) .savings-rate-tool {
26
+ --sr-ink: #f5f6ff;
27
+ --sr-muted: #b9c1df;
28
+ --sr-paper: #202947;
29
+ --sr-panel: #2b365b;
30
+ --sr-line: #4b5982;
31
+ --sr-accent: #9cacff;
32
+ --sr-accent-dark: #b9c4ff;
33
+ --sr-warm: #ffc95d;
34
+ --sr-coral: #ff9d8f;
35
+ --sr-sky: #303d67;
36
+ }
37
+
38
+ .savings-rate-workbench {
39
+ display: grid;
40
+ grid-template-columns: minmax(17rem, 0.88fr) minmax(20rem, 1.12fr);
41
+ min-width: 0;
42
+ overflow: hidden;
43
+ border: 2px solid var(--sr-line);
44
+ border-radius: 1.7rem;
45
+ background: var(--sr-paper);
46
+ box-shadow: 0 1.5rem 3rem rgba(32, 41, 77, 0.12);
47
+ }
48
+
49
+ .savings-rate-input-panel,
50
+ .savings-rate-results-panel {
51
+ min-width: 0;
52
+ padding: clamp(1.3rem, 3vw, 2.25rem);
53
+ }
54
+
55
+ .savings-rate-input-panel {
56
+ border-right: 2px solid var(--sr-line);
57
+ }
58
+
59
+ .savings-rate-results-panel {
60
+ background: var(--sr-panel);
61
+ }
62
+
63
+ .savings-rate-kicker {
64
+ margin-bottom: 0.35rem;
65
+ color: var(--sr-accent-dark);
66
+ font-size: 0.7rem;
67
+ font-weight: 900;
68
+ letter-spacing: 0.14em;
69
+ text-transform: uppercase;
70
+ }
71
+
72
+ .savings-rate-input-panel h2,
73
+ .savings-rate-results-panel h2,
74
+ .savings-rate-scenario-card h3 {
75
+ margin: 0;
76
+ color: var(--sr-ink);
77
+ }
78
+
79
+ .savings-rate-input-panel h2,
80
+ .savings-rate-results-panel h2 {
81
+ font-size: clamp(1.4rem, 3vw, 1.9rem);
82
+ letter-spacing: -0.025em;
83
+ }
84
+
85
+ .savings-rate-period-row,
86
+ .savings-rate-inline-row,
87
+ .savings-rate-results-topline,
88
+ .savings-rate-scenario-card-heading {
89
+ display: flex;
90
+ align-items: center;
91
+ justify-content: space-between;
92
+ gap: 0.8rem;
93
+ }
94
+
95
+ .savings-rate-period-row {
96
+ margin: 1.5rem 0 1.2rem;
97
+ }
98
+
99
+ .savings-rate-field-label,
100
+ .savings-rate-inline-row label {
101
+ color: var(--sr-muted);
102
+ font-size: 0.78rem;
103
+ font-weight: 900;
104
+ letter-spacing: 0.06em;
105
+ text-transform: uppercase;
106
+ }
107
+
108
+ .savings-rate-segmented {
109
+ display: inline-flex;
110
+ gap: 0.2rem;
111
+ padding: 0.25rem;
112
+ border: 1px solid var(--sr-line);
113
+ border-radius: 0.8rem;
114
+ background: var(--sr-panel);
115
+ }
116
+
117
+ .savings-rate-segment,
118
+ .savings-rate-button {
119
+ border: 0;
120
+ border-radius: 0.6rem;
121
+ cursor: pointer;
122
+ font: inherit;
123
+ font-weight: 900;
124
+ transition:
125
+ transform 0.18s ease,
126
+ background 0.18s ease,
127
+ filter 0.18s ease;
128
+ }
129
+
130
+ .savings-rate-segment {
131
+ padding: 0.52rem 0.75rem;
132
+ background: transparent;
133
+ color: var(--sr-muted);
134
+ font-size: 0.8rem;
135
+ }
136
+
137
+ .savings-rate-segment.is-active {
138
+ background: var(--sr-accent-dark);
139
+ color: #fff;
140
+ }
141
+
142
+ .savings-rate-segment:focus-visible,
143
+ .savings-rate-button:focus-visible,
144
+ .savings-rate-select:focus-visible {
145
+ outline: 3px solid var(--sr-warm);
146
+ outline-offset: 3px;
147
+ }
148
+
149
+ .savings-rate-inline-row {
150
+ margin-bottom: 1.2rem;
151
+ }
152
+
153
+ .savings-rate-select {
154
+ width: min(12.5rem, 60%);
155
+ border: 1px solid var(--sr-line);
156
+ border-radius: 0.65rem;
157
+ padding: 0.6rem 0.7rem;
158
+ background: var(--sr-panel);
159
+ color: var(--sr-ink);
160
+ font: inherit;
161
+ font-weight: 700;
162
+ }
163
+
164
+ .savings-rate-field {
165
+ margin: 1.05rem 0;
166
+ }
167
+
168
+ .savings-rate-field label {
169
+ display: block;
170
+ margin-bottom: 0.42rem;
171
+ color: var(--sr-ink);
172
+ font-size: 0.92rem;
173
+ font-weight: 900;
174
+ }
175
+
176
+ .savings-rate-field small,
177
+ .savings-rate-scenario-heading p {
178
+ display: block;
179
+ margin: 0.4rem 0 0;
180
+ color: var(--sr-muted);
181
+ font-size: 0.76rem;
182
+ line-height: 1.45;
183
+ }
184
+
185
+ .savings-rate-money-input,
186
+ .savings-rate-percent-input {
187
+ display: flex;
188
+ align-items: center;
189
+ border: 1px solid var(--sr-line);
190
+ border-radius: 0.75rem;
191
+ background: var(--sr-panel);
192
+ color: var(--sr-muted);
193
+ font-weight: 900;
194
+ }
195
+
196
+ .savings-rate-money-input span,
197
+ .savings-rate-percent-input span {
198
+ padding: 0 0.75rem;
199
+ }
200
+
201
+ .savings-rate-money-input input,
202
+ .savings-rate-percent-input input {
203
+ width: 100%;
204
+ min-width: 0;
205
+ border: 0;
206
+ outline: 0;
207
+ padding: 0.78rem 0.65rem;
208
+ background: transparent;
209
+ color: var(--sr-ink);
210
+ font: inherit;
211
+ font-size: 1.05rem;
212
+ font-weight: 900;
213
+ }
214
+
215
+ .savings-rate-money-input:focus-within,
216
+ .savings-rate-percent-input:focus-within,
217
+ .savings-rate-select:focus-visible {
218
+ border-color: var(--sr-accent);
219
+ outline: 3px solid color-mix(in srgb, var(--sr-accent) 34%, transparent);
220
+ outline-offset: 2px;
221
+ }
222
+
223
+ .savings-rate-scenario-inputs {
224
+ margin-top: 1.5rem;
225
+ border-top: 2px dotted var(--sr-line);
226
+ padding-top: 1.4rem;
227
+ }
228
+
229
+ .savings-rate-scenario-heading h3 {
230
+ font-size: 1rem;
231
+ }
232
+
233
+ .savings-rate-scenario-heading p {
234
+ margin-top: 0.25rem;
235
+ }
236
+
237
+ .savings-rate-two-fields {
238
+ display: grid;
239
+ grid-template-columns: 1fr 1fr;
240
+ gap: 0.75rem;
241
+ }
242
+
243
+ .savings-rate-actions {
244
+ display: flex;
245
+ flex-wrap: wrap;
246
+ gap: 0.6rem;
247
+ margin-top: 1.4rem;
248
+ }
249
+
250
+ .savings-rate-button {
251
+ padding: 0.78rem 1rem;
252
+ }
253
+
254
+ .savings-rate-button-muted {
255
+ border: 2px solid var(--sr-accent-dark);
256
+ background: transparent;
257
+ color: var(--sr-accent-dark);
258
+ }
259
+
260
+ .savings-rate-button-primary {
261
+ background: var(--sr-accent-dark);
262
+ color: #fff;
263
+ box-shadow: 0 0.45rem 0.9rem rgba(38, 57, 168, 0.2);
264
+ }
265
+
266
+ :global(.theme-dark) .savings-rate-button-primary {
267
+ color: #202947;
268
+ }
269
+
270
+ .savings-rate-button:hover,
271
+ .savings-rate-button:focus-visible {
272
+ transform: translateY(-2px);
273
+ filter: brightness(1.08);
274
+ }
275
+
276
+ .savings-rate-error {
277
+ margin: 0.85rem 0 0;
278
+ color: #b42318;
279
+ font-size: 0.85rem;
280
+ font-weight: 800;
281
+ }
282
+
283
+ :global(.theme-dark) .savings-rate-error {
284
+ color: #ffb4a9;
285
+ }
286
+
287
+ .savings-rate-period-badge {
288
+ border: 2px solid var(--sr-accent);
289
+ border-radius: 2rem;
290
+ padding: 0.45rem 0.7rem;
291
+ color: var(--sr-accent-dark);
292
+ font-size: 0.75rem;
293
+ font-weight: 900;
294
+ }
295
+
296
+ .savings-rate-illustration {
297
+ margin: 1.25rem 0 1.5rem;
298
+ overflow: hidden;
299
+ border: 1px solid color-mix(in srgb, var(--sr-accent) 20%, var(--sr-line));
300
+ border-radius: 1.15rem;
301
+ background: var(--sr-sky);
302
+ }
303
+
304
+ .savings-rate-illustration svg {
305
+ display: block;
306
+ width: 100%;
307
+ height: auto;
308
+ }
309
+
310
+ .savings-rate-illustration-sun {
311
+ fill: var(--sr-warm);
312
+ }
313
+
314
+ .savings-rate-illustration-cloud {
315
+ fill: color-mix(in srgb, var(--sr-paper) 78%, var(--sr-sky));
316
+ }
317
+
318
+ .savings-rate-illustration-road {
319
+ fill: none;
320
+ stroke: color-mix(in srgb, var(--sr-accent) 30%, var(--sr-sky));
321
+ stroke-linecap: round;
322
+ stroke-width: 32;
323
+ }
324
+
325
+ .savings-rate-illustration-road-line {
326
+ fill: none;
327
+ stroke: color-mix(in srgb, var(--sr-paper) 84%, var(--sr-sky));
328
+ stroke-dasharray: 16 13;
329
+ stroke-linecap: round;
330
+ stroke-width: 4;
331
+ }
332
+
333
+ .savings-rate-illustration-jar {
334
+ fill: var(--sr-coral);
335
+ stroke: var(--sr-ink);
336
+ stroke-width: 3;
337
+ }
338
+
339
+ .savings-rate-illustration-lid {
340
+ fill: var(--sr-warm);
341
+ stroke: var(--sr-ink);
342
+ stroke-width: 3;
343
+ }
344
+
345
+ .savings-rate-illustration-jar-line {
346
+ fill: none;
347
+ stroke: color-mix(in srgb, var(--sr-paper) 88%, var(--sr-coral));
348
+ stroke-linecap: round;
349
+ stroke-width: 4;
350
+ }
351
+
352
+ .savings-rate-illustration-coin {
353
+ fill: var(--sr-warm);
354
+ stroke: var(--sr-ink);
355
+ stroke-width: 3;
356
+ }
357
+
358
+ .savings-rate-illustration-coin-light,
359
+ .savings-rate-illustration-spark {
360
+ fill: var(--sr-paper);
361
+ stroke: var(--sr-ink);
362
+ stroke-width: 2;
363
+ }
364
+
365
+ .savings-rate-illustration-flag {
366
+ fill: none;
367
+ stroke: var(--sr-ink);
368
+ stroke-linecap: round;
369
+ stroke-width: 4;
370
+ }
371
+
372
+ .savings-rate-illustration-flag-fill {
373
+ fill: var(--sr-coral);
374
+ }
375
+
376
+ .savings-rate-hero {
377
+ display: grid;
378
+ grid-template-columns: 11rem 1fr;
379
+ align-items: center;
380
+ gap: clamp(1rem, 4vw, 2rem);
381
+ margin: 1.25rem 0 2rem;
382
+ }
383
+
384
+ .savings-rate-ring {
385
+ --rate: 108deg;
386
+
387
+ display: grid;
388
+ width: min(11rem, 100%);
389
+ aspect-ratio: 1;
390
+ place-items: center;
391
+ border-radius: 50%;
392
+ background: conic-gradient(
393
+ var(--sr-accent) var(--rate),
394
+ color-mix(in srgb, var(--sr-line) 62%, transparent) 0
395
+ );
396
+ transform: rotate(-90deg);
397
+ }
398
+
399
+ .savings-rate-ring-inner {
400
+ display: grid;
401
+ width: 76%;
402
+ aspect-ratio: 1;
403
+ place-items: center;
404
+ align-content: center;
405
+ border-radius: 50%;
406
+ background: var(--sr-paper);
407
+ text-align: center;
408
+ transform: rotate(90deg);
409
+ }
410
+
411
+ .savings-rate-ring-inner strong {
412
+ color: var(--sr-ink);
413
+ font-size: clamp(1.7rem, 5vw, 2.6rem);
414
+ line-height: 1;
415
+ }
416
+
417
+ .savings-rate-ring-inner span {
418
+ margin-top: 0.35rem;
419
+ color: var(--sr-muted);
420
+ font-size: 0.7rem;
421
+ font-weight: 900;
422
+ text-transform: uppercase;
423
+ }
424
+
425
+ .savings-rate-status {
426
+ margin: 0;
427
+ color: var(--sr-accent-dark);
428
+ font-size: 1.2rem;
429
+ font-weight: 900;
430
+ line-height: 1.2;
431
+ }
432
+
433
+ .savings-rate-hero-copy > p:last-child {
434
+ margin: 0.65rem 0 0;
435
+ color: var(--sr-muted);
436
+ font-size: 0.9rem;
437
+ line-height: 1.5;
438
+ }
439
+
440
+ .savings-rate-metric-grid,
441
+ .savings-rate-scenario-metrics {
442
+ display: grid;
443
+ grid-template-columns: 1fr 1fr;
444
+ gap: 0.65rem;
445
+ margin: 0;
446
+ }
447
+
448
+ .savings-rate-metric-grid div,
449
+ .savings-rate-scenario-metrics div {
450
+ min-width: 0;
451
+ border: 1px solid var(--sr-line);
452
+ border-radius: 0.8rem;
453
+ padding: 0.85rem;
454
+ background: color-mix(in srgb, var(--sr-paper) 68%, transparent);
455
+ }
456
+
457
+ .savings-rate-metric-grid dt,
458
+ .savings-rate-scenario-metrics dt {
459
+ color: var(--sr-muted);
460
+ font-size: 0.7rem;
461
+ font-weight: 900;
462
+ letter-spacing: 0.04em;
463
+ text-transform: uppercase;
464
+ }
465
+
466
+ .savings-rate-metric-grid dd,
467
+ .savings-rate-scenario-metrics dd {
468
+ margin: 0.35rem 0 0;
469
+ color: var(--sr-ink);
470
+ font-size: 1.05rem;
471
+ font-weight: 900;
472
+ overflow-wrap: anywhere;
473
+ }
474
+
475
+ .savings-rate-scenario-card {
476
+ margin-top: 1.5rem;
477
+ border: 2px solid color-mix(in srgb, var(--sr-warm) 70%, var(--sr-line));
478
+ border-radius: 1rem;
479
+ padding: 1.1rem;
480
+ background: color-mix(in srgb, var(--sr-warm) 12%, var(--sr-paper));
481
+ }
482
+
483
+ .savings-rate-scenario-card h3 {
484
+ font-size: 1rem;
485
+ }
486
+
487
+ .savings-rate-scenario-card-heading > strong {
488
+ color: var(--sr-accent-dark);
489
+ font-size: 1.5rem;
490
+ }
491
+
492
+ .savings-rate-scenario-bar {
493
+ position: relative;
494
+ height: 0.65rem;
495
+ margin: 1.3rem 0 0.4rem;
496
+ border-radius: 1rem;
497
+ background: var(--sr-line);
498
+ }
499
+
500
+ .savings-rate-scenario-bar span {
501
+ display: block;
502
+ width: 0;
503
+ height: 100%;
504
+ border-radius: inherit;
505
+ background: var(--sr-accent-dark);
506
+ transition: width 0.25s ease;
507
+ }
508
+
509
+ .savings-rate-scenario-bar i {
510
+ position: absolute;
511
+ top: 50%;
512
+ width: 0.9rem;
513
+ height: 0.9rem;
514
+ border: 2px solid var(--sr-paper);
515
+ border-radius: 50%;
516
+ background: var(--sr-coral);
517
+ box-shadow: 0 0 0 2px var(--sr-coral);
518
+ transform: translate(-50%, -50%);
519
+ }
520
+
521
+ .savings-rate-scenario-summary {
522
+ display: flex;
523
+ justify-content: space-between;
524
+ gap: 0.5rem;
525
+ color: var(--sr-muted);
526
+ font-size: 0.74rem;
527
+ }
528
+
529
+ .savings-rate-scenario-summary span:first-child {
530
+ color: var(--sr-accent-dark);
531
+ font-weight: 900;
532
+ }
533
+
534
+ .savings-rate-scenario-metrics {
535
+ margin-top: 1rem;
536
+ }
537
+
538
+ @media (max-width: 760px) {
539
+ .savings-rate-workbench {
540
+ grid-template-columns: 1fr;
541
+ }
542
+
543
+ .savings-rate-input-panel {
544
+ border-right: 0;
545
+ border-bottom: 2px solid var(--sr-line);
546
+ }
547
+ }
548
+
549
+ @media (max-width: 480px) {
550
+ .savings-rate-period-row,
551
+ .savings-rate-inline-row {
552
+ align-items: flex-start;
553
+ flex-direction: column;
554
+ }
555
+
556
+ .savings-rate-select {
557
+ width: 100%;
558
+ }
559
+
560
+ .savings-rate-hero {
561
+ grid-template-columns: 1fr;
562
+ justify-items: center;
563
+ text-align: center;
564
+ }
565
+
566
+ .savings-rate-hero-copy {
567
+ width: 100%;
568
+ }
569
+
570
+ .savings-rate-two-fields,
571
+ .savings-rate-metric-grid,
572
+ .savings-rate-scenario-metrics {
573
+ grid-template-columns: 1fr;
574
+ }
575
+ }
@@ -0,0 +1,11 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { savingsRate } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props { locale?: KnownLocale; }
7
+ const { locale = 'en' } = Astro.props;
8
+ const content = await savingsRate.i18n[locale]?.() ?? await savingsRate.i18n.en?.();
9
+ ---
10
+
11
+ {content && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,48 @@
1
+ export interface SavingsRateUI extends Record<string, string> {
2
+ labelMoneyPicture: string;
3
+ labelSavingsSnapshot: string;
4
+ labelTrySmallChange: string;
5
+ labelPeriod: string;
6
+ labelMonthly: string;
7
+ labelYearly: string;
8
+ labelCurrency: string;
9
+ labelCurrencyUSD: string;
10
+ labelCurrencyEUR: string;
11
+ labelCurrencyGBP: string;
12
+ labelCurrencyCAD: string;
13
+ labelCurrencyAUD: string;
14
+ labelCurrencyJPY: string;
15
+ labelIncome: string;
16
+ labelIncomeHelp: string;
17
+ labelSaved: string;
18
+ labelSavedHelp: string;
19
+ labelExtraContribution: string;
20
+ labelExtraContributionHelp: string;
21
+ labelTargetRate: string;
22
+ labelTargetRateHelp: string;
23
+ labelIncomeChange: string;
24
+ labelSpendingChange: string;
25
+ labelScenarioHelp: string;
26
+ labelCurrentRate: string;
27
+ labelAnnualSaved: string;
28
+ labelAnnualIncome: string;
29
+ labelSpending: string;
30
+ labelTargetGap: string;
31
+ labelTargetMet: string;
32
+ labelMoreNeeded: string;
33
+ labelScenario: string;
34
+ labelScenarioRate: string;
35
+ labelScenarioChange: string;
36
+ labelScenarioSaved: string;
37
+ labelScenarioSpending: string;
38
+ labelScenarioTarget: string;
39
+ labelScenarioTargetMet: string;
40
+ labelScenarioMoreNeeded: string;
41
+ labelReset: string;
42
+ labelCopyResult: string;
43
+ labelCopied: string;
44
+ labelInvalidInput: string;
45
+ labelRate: string;
46
+ labelPercentagePoints: string;
47
+ labelMoneySuffix: string;
48
+ }
package/src/tools.ts CHANGED
@@ -2,6 +2,7 @@ export { ALL_ENTRIES } from './entries';
2
2
  import type { ToolDefinition } from './types';
3
3
  import { COMPOUND_INTEREST_TOOL } from './tool/compoundInterest';
4
4
  import { FINANCIAL_FREEDOM_TOOL } from './tool/financialFreedom';
5
+ import { SAVINGS_RATE_TOOL } from './tool/savingsRate';
5
6
  import { PROFITABILITY_TOOL } from './tool/profitability';
6
7
  import { MORTGAGE_TOOL } from './tool/mortgage';
7
8
  import { INFLATION_TOOL } from './tool/inflation';
@@ -23,4 +24,4 @@ import { INFLATION_PURCHASING_POWER_TOOL } from './tool/inflationPurchasingPower
23
24
  import { SUBSCRIPTION_COST_ANNUALIZER_TOOL } from './tool/subscriptionCostAnnualizer';
24
25
  import { LOAN_TO_INCOME_RATIO_TOOL } from './tool/loanToIncomeRatio';
25
26
 
26
- export const ALL_TOOLS: ToolDefinition[] = [COMPOUND_INTEREST_TOOL, FINANCIAL_FREEDOM_TOOL, PROFITABILITY_TOOL, MORTGAGE_TOOL, INFLATION_TOOL, PERCENTAGE_CALCULATOR_TOOL, LATE_INTEREST_TOOL, IBAN_BIC_SWIFT_TOOL, RENT_INCREASE_TOOL, LOTTERY_OPTIMIZER_TOOL, COURT_FEE_CALCULATOR_TOOL, LEGAL_INTEREST_RATE_TOOL, FIRE_CALCULATOR_TOOL, DEBT_SNOWBALL_TOOL, REVOLVING_CARD_CALCULATOR_TOOL, PESETA_VALUE_TOOL, SALARY_EMPLOYER_COST_TOOL, DIVIDEND_YIELD_TOOL, MORTGAGE_EXTRA_PAYMENT_PLANNER_TOOL, INFLATION_PURCHASING_POWER_TOOL, SUBSCRIPTION_COST_ANNUALIZER_TOOL, LOAN_TO_INCOME_RATIO_TOOL];
27
+ export const ALL_TOOLS: ToolDefinition[] = [COMPOUND_INTEREST_TOOL, FINANCIAL_FREEDOM_TOOL, SAVINGS_RATE_TOOL, PROFITABILITY_TOOL, MORTGAGE_TOOL, INFLATION_TOOL, PERCENTAGE_CALCULATOR_TOOL, LATE_INTEREST_TOOL, IBAN_BIC_SWIFT_TOOL, RENT_INCREASE_TOOL, LOTTERY_OPTIMIZER_TOOL, COURT_FEE_CALCULATOR_TOOL, LEGAL_INTEREST_RATE_TOOL, FIRE_CALCULATOR_TOOL, DEBT_SNOWBALL_TOOL, REVOLVING_CARD_CALCULATOR_TOOL, PESETA_VALUE_TOOL, SALARY_EMPLOYER_COST_TOOL, DIVIDEND_YIELD_TOOL, MORTGAGE_EXTRA_PAYMENT_PLANNER_TOOL, INFLATION_PURCHASING_POWER_TOOL, SUBSCRIPTION_COST_ANNUALIZER_TOOL, LOAN_TO_INCOME_RATIO_TOOL];