mantenimento-app 2.4.4 → 2.4.6

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/app.js CHANGED
@@ -289,7 +289,7 @@ const defaultExpenseItems = [
289
289
  firstHomeAssignedToHint: "Seleziona il coniuge a cui e ceduta la prima casa.",
290
290
  firstHomeAssignedToNone: "Nessuna cessione",
291
291
  firstHomeAssignedToSpouse: "Casa ceduta a {spouse}",
292
- firstHomeSplitLabel: "Quota mutuo a carico {spouse} (%)",
292
+ firstHomeSplitLabel: "Quota mutuo a carico",
293
293
  firstHomeSplitHint: "Percentuale della rata mutuo pagata da {spouse}. La quota dell'altro coniuge e complementare a 100%.",
294
294
  firstHomeSplitInfo: "Ripartizione mutuo: {spouse1} {p1}% · {spouse2} {p2}%",
295
295
  calcCompBenefitsLabel: "Benefici compensativi gia allocati",
@@ -651,7 +651,7 @@ const defaultExpenseItems = [
651
651
  firstHomeAssignedToHint: "Select which spouse receives assignment of the primary home.",
652
652
  firstHomeAssignedToNone: "No assignment",
653
653
  firstHomeAssignedToSpouse: "Home assigned to {spouse}",
654
- firstHomeSplitLabel: "Mortgage share paid by {spouse} (%)",
654
+ firstHomeSplitLabel: "Mortgage share allocation",
655
655
  firstHomeSplitHint: "Percentage of the monthly mortgage payment paid by {spouse}. The other spouse share is the complement to 100%.",
656
656
  firstHomeSplitInfo: "Mortgage split: {spouse1} {p1}% · {spouse2} {p2}%",
657
657
  calcCompBenefitsLabel: "Compensative benefits already allocated",
@@ -1290,7 +1290,7 @@ const defaultExpenseItems = [
1290
1290
  if (hintPrimaCasaMutuoImporto) hintPrimaCasaMutuoImporto.title = tr("firstHomeMortgageAmountHint");
1291
1291
  if (lblPrimaCasaAssegnataA) lblPrimaCasaAssegnataA.textContent = tr("firstHomeAssignedToLabel");
1292
1292
  if (hintPrimaCasaAssegnataA) hintPrimaCasaAssegnataA.title = tr("firstHomeAssignedToHint");
1293
- if (lblPrimaCasaMutuoPerc1) lblPrimaCasaMutuoPerc1.textContent = msg("firstHomeSplitLabel", { spouse: c1n() });
1293
+ if (lblPrimaCasaMutuoPerc1) lblPrimaCasaMutuoPerc1.textContent = tr("firstHomeSplitLabel");
1294
1294
  if (hintPrimaCasaMutuoPerc1) hintPrimaCasaMutuoPerc1.title = msg("firstHomeSplitHint", { spouse: c1n() });
1295
1295
  if (lblStraordAnn1) lblStraordAnn1.textContent = msg("extraAnnLabel1", { spouse: c1n(), currency: currentCurrency });
1296
1296
  if (lblStraordAnn2) lblStraordAnn2.textContent = msg("extraAnnLabel2", { spouse: c2n(), currency: currentCurrency });
@@ -3931,7 +3931,7 @@ const defaultExpenseItems = [
3931
3931
  const amount = Math.max(0, num("primaCasaMutuoImporto"));
3932
3932
  const quota1 = amount * (normalizedShare1 / 100);
3933
3933
  const quota2 = amount - quota1;
3934
- if (splitLabelEl) splitLabelEl.textContent = msg("firstHomeSplitLabel", { spouse: c1n() });
3934
+ if (splitLabelEl) splitLabelEl.textContent = tr("firstHomeSplitLabel");
3935
3935
  if (splitHintEl) splitHintEl.title = msg("firstHomeSplitHint", { spouse: c1n() });
3936
3936
  if (splitInfoEl) {
3937
3937
  splitInfoEl.textContent = msg("firstHomeSplitInfo", {
@@ -6469,6 +6469,19 @@ ${scenarioLab.length ? `
6469
6469
  }
6470
6470
  });
6471
6471
 
6472
+ const firstHomeShiftLeftBtn = document.getElementById("primaCasaMutuoShiftLeft");
6473
+ const firstHomeShiftRightBtn = document.getElementById("primaCasaMutuoShiftRight");
6474
+ const firstHomeShareInput = document.getElementById("primaCasaMutuoPerc1");
6475
+ const shiftFirstHomeShare = (delta) => {
6476
+ if (!firstHomeShareInput || firstHomeShareInput.disabled) return;
6477
+ const next = Math.min(100, Math.max(0, Number(firstHomeShareInput.value || 0) + delta));
6478
+ firstHomeShareInput.value = String(next);
6479
+ updateFirstHomeMortgageUi();
6480
+ renderAll();
6481
+ };
6482
+ if (firstHomeShiftLeftBtn) firstHomeShiftLeftBtn.addEventListener("click", () => shiftFirstHomeShare(-1));
6483
+ if (firstHomeShiftRightBtn) firstHomeShiftRightBtn.addEventListener("click", () => shiftFirstHomeShare(1));
6484
+
6472
6485
  document.getElementById("langSelect").addEventListener("change", (e) => {
6473
6486
  const next = String(e.target.value || "it").toLowerCase();
6474
6487
  currentLang = SUPPORTED_LANGS.includes(next) ? next : "it";
@@ -289,7 +289,7 @@ const defaultExpenseItems = [
289
289
  firstHomeAssignedToHint: "Seleziona il coniuge a cui e ceduta la prima casa.",
290
290
  firstHomeAssignedToNone: "Nessuna cessione",
291
291
  firstHomeAssignedToSpouse: "Casa ceduta a {spouse}",
292
- firstHomeSplitLabel: "Quota mutuo a carico {spouse} (%)",
292
+ firstHomeSplitLabel: "Quota mutuo a carico",
293
293
  firstHomeSplitHint: "Percentuale della rata mutuo pagata da {spouse}. La quota dell'altro coniuge e complementare a 100%.",
294
294
  firstHomeSplitInfo: "Ripartizione mutuo: {spouse1} {p1}% · {spouse2} {p2}%",
295
295
  calcCompBenefitsLabel: "Benefici compensativi gia allocati",
@@ -651,7 +651,7 @@ const defaultExpenseItems = [
651
651
  firstHomeAssignedToHint: "Select which spouse receives assignment of the primary home.",
652
652
  firstHomeAssignedToNone: "No assignment",
653
653
  firstHomeAssignedToSpouse: "Home assigned to {spouse}",
654
- firstHomeSplitLabel: "Mortgage share paid by {spouse} (%)",
654
+ firstHomeSplitLabel: "Mortgage share allocation",
655
655
  firstHomeSplitHint: "Percentage of the monthly mortgage payment paid by {spouse}. The other spouse share is the complement to 100%.",
656
656
  firstHomeSplitInfo: "Mortgage split: {spouse1} {p1}% · {spouse2} {p2}%",
657
657
  calcCompBenefitsLabel: "Compensative benefits already allocated",
@@ -1290,7 +1290,7 @@ const defaultExpenseItems = [
1290
1290
  if (hintPrimaCasaMutuoImporto) hintPrimaCasaMutuoImporto.title = tr("firstHomeMortgageAmountHint");
1291
1291
  if (lblPrimaCasaAssegnataA) lblPrimaCasaAssegnataA.textContent = tr("firstHomeAssignedToLabel");
1292
1292
  if (hintPrimaCasaAssegnataA) hintPrimaCasaAssegnataA.title = tr("firstHomeAssignedToHint");
1293
- if (lblPrimaCasaMutuoPerc1) lblPrimaCasaMutuoPerc1.textContent = msg("firstHomeSplitLabel", { spouse: c1n() });
1293
+ if (lblPrimaCasaMutuoPerc1) lblPrimaCasaMutuoPerc1.textContent = tr("firstHomeSplitLabel");
1294
1294
  if (hintPrimaCasaMutuoPerc1) hintPrimaCasaMutuoPerc1.title = msg("firstHomeSplitHint", { spouse: c1n() });
1295
1295
  if (lblStraordAnn1) lblStraordAnn1.textContent = msg("extraAnnLabel1", { spouse: c1n(), currency: currentCurrency });
1296
1296
  if (lblStraordAnn2) lblStraordAnn2.textContent = msg("extraAnnLabel2", { spouse: c2n(), currency: currentCurrency });
@@ -3931,7 +3931,7 @@ const defaultExpenseItems = [
3931
3931
  const amount = Math.max(0, num("primaCasaMutuoImporto"));
3932
3932
  const quota1 = amount * (normalizedShare1 / 100);
3933
3933
  const quota2 = amount - quota1;
3934
- if (splitLabelEl) splitLabelEl.textContent = msg("firstHomeSplitLabel", { spouse: c1n() });
3934
+ if (splitLabelEl) splitLabelEl.textContent = tr("firstHomeSplitLabel");
3935
3935
  if (splitHintEl) splitHintEl.title = msg("firstHomeSplitHint", { spouse: c1n() });
3936
3936
  if (splitInfoEl) {
3937
3937
  splitInfoEl.textContent = msg("firstHomeSplitInfo", {
@@ -6469,6 +6469,19 @@ ${scenarioLab.length ? `
6469
6469
  }
6470
6470
  });
6471
6471
 
6472
+ const firstHomeShiftLeftBtn = document.getElementById("primaCasaMutuoShiftLeft");
6473
+ const firstHomeShiftRightBtn = document.getElementById("primaCasaMutuoShiftRight");
6474
+ const firstHomeShareInput = document.getElementById("primaCasaMutuoPerc1");
6475
+ const shiftFirstHomeShare = (delta) => {
6476
+ if (!firstHomeShareInput || firstHomeShareInput.disabled) return;
6477
+ const next = Math.min(100, Math.max(0, Number(firstHomeShareInput.value || 0) + delta));
6478
+ firstHomeShareInput.value = String(next);
6479
+ updateFirstHomeMortgageUi();
6480
+ renderAll();
6481
+ };
6482
+ if (firstHomeShiftLeftBtn) firstHomeShiftLeftBtn.addEventListener("click", () => shiftFirstHomeShare(-1));
6483
+ if (firstHomeShiftRightBtn) firstHomeShiftRightBtn.addEventListener("click", () => shiftFirstHomeShare(1));
6484
+
6472
6485
  document.getElementById("langSelect").addEventListener("change", (e) => {
6473
6486
  const next = String(e.target.value || "it").toLowerCase();
6474
6487
  currentLang = SUPPORTED_LANGS.includes(next) ? next : "it";
@@ -88,7 +88,7 @@
88
88
  ]
89
89
  }
90
90
  </script>
91
- <link rel="stylesheet" href="styles.css" />
91
+ <link rel="stylesheet" href="styles.css?v=2.4.6" />
92
92
  </head>
93
93
  <body>
94
94
  <div class="wrap">
@@ -380,8 +380,8 @@
380
380
  </label>
381
381
  <input id="primaCasaMutuoImporto" type="number" min="0" step="50" value="0" />
382
382
  </div>
383
- <div class="field">
384
- <label for="primaCasaMutuoPerc1" class="label-row"><span id="lblPrimaCasaMutuoPerc1">Quota mutuo a carico Coniuge 1 (%)</span>
383
+ <div class="field first-home-split-field">
384
+ <label for="primaCasaMutuoPerc1" class="label-row"><span id="lblPrimaCasaMutuoPerc1">Quota mutuo a carico</span>
385
385
  <span class="hint" id="hintPrimaCasaMutuoPerc1" title="Percentuale della rata mutuo pagata da Coniuge 1. La quota dell'altro coniuge e complementare a 100%.">i</span>
386
386
  </label>
387
387
  <div class="mortgage-split-slider" id="primaCasaMutuoSliderWrap">
@@ -390,7 +390,11 @@
390
390
  <div class="mortgage-split-amount" id="primaCasaSplitLeftAmount">0 EUR</div>
391
391
  </div>
392
392
  <div class="mortgage-split-range-wrap">
393
- <input id="primaCasaMutuoPerc1" type="range" min="0" max="100" step="1" value="50" aria-label="Ripartizione quota mutuo" />
393
+ <div class="mortgage-split-range-controls">
394
+ <button id="primaCasaMutuoShiftLeft" class="mortgage-split-nudge" type="button" aria-label="Sposta quota verso sinistra" title="Sposta quota verso sinistra">&#9664;</button>
395
+ <input id="primaCasaMutuoPerc1" type="range" min="0" max="100" step="1" value="50" aria-label="Ripartizione quota mutuo" />
396
+ <button id="primaCasaMutuoShiftRight" class="mortgage-split-nudge" type="button" aria-label="Sposta quota verso destra" title="Sposta quota verso destra">&#9654;</button>
397
+ </div>
394
398
  <div class="mortgage-split-center" id="primaCasaSplitCenter">50% / 50%</div>
395
399
  </div>
396
400
  <div class="mortgage-split-side mortgage-split-side-right" id="primaCasaSplitRight">
@@ -626,7 +630,7 @@
626
630
  <script src="supabase.min.js"></script>
627
631
  <script src="fabric.min.js"></script>
628
632
  <script src="html2pdf.bundle.min.js"></script>
629
- <script src="app.js?v=2.4.4"></script>
633
+ <script src="app.js?v=2.4.6"></script>
630
634
  </body>
631
635
  </html>
632
636
 
@@ -887,9 +887,26 @@
887
887
  .extra-box-first-home {
888
888
  position: relative;
889
889
  overflow: hidden;
890
- background: linear-gradient(135deg, #ffffff 0%, #f0fffe 50%, #f5faff 100%);
891
- border: 1px solid rgba(27, 141, 127, 0.15);
892
- box-shadow: 0 2px 8px rgba(27, 141, 127, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8);
890
+ background:
891
+ linear-gradient(160deg, rgba(255, 255, 255, 0.92), rgba(242, 252, 250, 0.96) 46%, rgba(246, 251, 255, 0.94)),
892
+ repeating-linear-gradient(135deg, rgba(27, 141, 127, 0.035) 0 10px, rgba(216, 154, 53, 0.03) 10px 20px);
893
+ border: 1px solid rgba(27, 141, 127, 0.2);
894
+ box-shadow: 0 8px 20px rgba(16, 88, 79, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.86);
895
+ transition: transform 0.26s ease, box-shadow 0.26s ease, border-color 0.26s ease;
896
+ }
897
+
898
+ .extra-box-first-home:hover {
899
+ transform: translateY(-2px);
900
+ border-color: rgba(27, 141, 127, 0.32);
901
+ box-shadow: 0 14px 28px rgba(16, 88, 79, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.9);
902
+ }
903
+
904
+ .extra-box-first-home::before {
905
+ content: "";
906
+ position: absolute;
907
+ inset: 0;
908
+ background: linear-gradient(115deg, rgba(255, 255, 255, 0.24), transparent 44%, rgba(61, 181, 160, 0.11) 72%, transparent 100%);
909
+ pointer-events: none;
893
910
  }
894
911
 
895
912
  .extra-box-first-home::after {
@@ -907,19 +924,45 @@
907
924
  margin-right: 4px;
908
925
  }
909
926
 
927
+ .extra-box-first-home .extra-box-title {
928
+ font-size: 0.96rem;
929
+ font-weight: 800;
930
+ letter-spacing: 0.25px;
931
+ color: #114942;
932
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
933
+ }
934
+
935
+ .extra-box-first-home .extra-box-note {
936
+ margin-top: 4px;
937
+ padding-left: 11px;
938
+ border-left: 3px solid rgba(27, 141, 127, 0.35);
939
+ color: #2f5853;
940
+ }
941
+
910
942
  .extra-box-first-home .extra-grid {
911
943
  position: relative;
912
944
  z-index: 1;
913
945
  gap: 8px 10px;
914
946
  }
915
947
 
948
+ .extra-box-first-home .first-home-split-field {
949
+ grid-column: 1 / -1;
950
+ }
951
+
916
952
  .extra-box-first-home .field {
917
- transition: transform 0.2s ease, filter 0.2s ease;
953
+ border-radius: 12px;
954
+ padding: 8px 9px 7px;
955
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.62), rgba(241, 249, 247, 0.58));
956
+ border: 1px solid rgba(27, 141, 127, 0.12);
957
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
958
+ transition: transform 0.2s ease, filter 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
918
959
  }
919
960
 
920
961
  .extra-box-first-home .field:focus-within {
921
962
  transform: translateY(-1px);
922
963
  filter: saturate(1.04);
964
+ border-color: rgba(27, 141, 127, 0.32);
965
+ box-shadow: 0 8px 16px rgba(22, 104, 93, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.84);
923
966
  }
924
967
 
925
968
  .extra-box-first-home .field input[type="number"],
@@ -929,6 +972,15 @@
929
972
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
930
973
  }
931
974
 
975
+ .extra-box-first-home #primaCasaMutuoEnabled {
976
+ width: 20px;
977
+ height: 20px;
978
+ accent-color: #0e9886;
979
+ margin-top: 6px;
980
+ box-shadow: 0 0 0 4px rgba(14, 152, 134, 0.14);
981
+ border-radius: 6px;
982
+ }
983
+
932
984
  .extra-box-first-home .field input[type="number"]:focus,
933
985
  .extra-box-first-home .field select:focus {
934
986
  border-color: rgba(27, 141, 127, 0.4);
@@ -951,7 +1003,7 @@
951
1003
  grid-template-columns: minmax(0, 1fr) minmax(180px, 2fr) minmax(0, 1fr);
952
1004
  gap: 10px;
953
1005
  align-items: center;
954
- box-shadow: 0 4px 12px rgba(27, 141, 127, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.6);
1006
+ box-shadow: 0 10px 18px rgba(27, 141, 127, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.65);
955
1007
  transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
956
1008
  }
957
1009
 
@@ -966,7 +1018,7 @@
966
1018
  }
967
1019
 
968
1020
  .mortgage-split-slider:hover {
969
- box-shadow: 0 8px 20px rgba(27, 141, 127, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.8);
1021
+ box-shadow: 0 14px 28px rgba(27, 141, 127, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.86);
970
1022
  border-color: rgba(27, 141, 127, 0.3);
971
1023
  }
972
1024
 
@@ -1072,6 +1124,44 @@
1072
1124
  --split-left: 50%;
1073
1125
  }
1074
1126
 
1127
+ .mortgage-split-range-controls {
1128
+ display: grid;
1129
+ grid-template-columns: 34px minmax(0, 1fr) 34px;
1130
+ gap: 7px;
1131
+ align-items: center;
1132
+ }
1133
+
1134
+ .mortgage-split-nudge {
1135
+ height: 32px;
1136
+ width: 32px;
1137
+ border-radius: 50%;
1138
+ border: 1.5px solid rgba(27, 141, 127, 0.24);
1139
+ background: linear-gradient(180deg, #ffffff, #edf8f5);
1140
+ color: #11655b;
1141
+ font-size: 13px;
1142
+ font-weight: 900;
1143
+ line-height: 1;
1144
+ cursor: pointer;
1145
+ box-shadow: 0 2px 8px rgba(17, 93, 84, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.85);
1146
+ transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
1147
+ }
1148
+
1149
+ .mortgage-split-nudge:hover {
1150
+ transform: translateY(-1px) scale(1.04);
1151
+ border-color: rgba(27, 141, 127, 0.38);
1152
+ box-shadow: 0 4px 12px rgba(17, 93, 84, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.9);
1153
+ }
1154
+
1155
+ .mortgage-split-nudge:active {
1156
+ transform: translateY(0) scale(0.98);
1157
+ }
1158
+
1159
+ .mortgage-split-slider.is-disabled .mortgage-split-nudge {
1160
+ opacity: 0.6;
1161
+ cursor: not-allowed;
1162
+ transform: none;
1163
+ }
1164
+
1075
1165
  .mortgage-split-range-wrap input[type="range"] {
1076
1166
  -webkit-appearance: none;
1077
1167
  appearance: none;
@@ -1165,8 +1255,17 @@
1165
1255
  }
1166
1256
 
1167
1257
  #primaCasaMutuoSplitInfo {
1168
- margin-top: 3px;
1169
- font-size: 0.77rem;
1258
+ margin-top: 7px;
1259
+ font-size: 0.79rem;
1260
+ font-weight: 700;
1261
+ color: #174e47;
1262
+ background: linear-gradient(90deg, rgba(22, 163, 150, 0.12), rgba(216, 154, 53, 0.12));
1263
+ border: 1px solid rgba(22, 163, 150, 0.14);
1264
+ border-radius: 999px;
1265
+ padding: 4px 10px;
1266
+ display: inline-flex;
1267
+ align-items: center;
1268
+ gap: 4px;
1170
1269
  }
1171
1270
 
1172
1271
  .label-row {
@@ -3438,6 +3537,16 @@
3438
3537
  .mortgage-split-range-wrap {
3439
3538
  order: -1;
3440
3539
  }
3540
+
3541
+ .mortgage-split-range-controls {
3542
+ grid-template-columns: 30px minmax(0, 1fr) 30px;
3543
+ }
3544
+
3545
+ .mortgage-split-nudge {
3546
+ height: 28px;
3547
+ width: 28px;
3548
+ font-size: 12px;
3549
+ }
3441
3550
  .spieg-grid {
3442
3551
  grid-template-columns: 1fr;
3443
3552
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mantenimento-app",
3
- "version": "2.4.4",
3
+ "version": "2.4.6",
4
4
  "description": "Frontend + backend architecture for the mantenimento calculator",
5
5
  "type": "commonjs",
6
6
  "main": "backend/calculate-model.js",