mantenimento-app 2.4.1 → 2.4.2
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 +39 -13
- package/frontend/public/app.js +39 -13
- package/frontend/public/index.html +1 -1
- package/frontend/public/styles.css +64 -0
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -295,6 +295,7 @@ const defaultExpenseItems = [
|
|
|
295
295
|
calcBenefitFamilyAllowance: "Assegno familiare INPS percepito da {spouse}",
|
|
296
296
|
calcBenefitPrimaryHomeMortgage: "Quota mutuo prima casa ceduta al collocatario ({payer} -> {receiver})",
|
|
297
297
|
calcBenefitPrimaryHomeAssignment: "Assegnazione casa familiare - valore locativo ({receiver})",
|
|
298
|
+
calcBenefitExcludedFromTotal: "fuori totale",
|
|
298
299
|
pdfCompBenefitsSection: "Benefici compensativi gia allocati",
|
|
299
300
|
pdfCompBenefitsItem: "Beneficio",
|
|
300
301
|
pdfCompBenefitsAmount: "Valore {currency}/mese",
|
|
@@ -654,6 +655,7 @@ const defaultExpenseItems = [
|
|
|
654
655
|
calcBenefitFamilyAllowance: "INPS family allowance received by {spouse}",
|
|
655
656
|
calcBenefitPrimaryHomeMortgage: "Primary-home mortgage share assigned to custodial parent ({payer} -> {receiver})",
|
|
656
657
|
calcBenefitPrimaryHomeAssignment: "Primary home assignment - rental value ({receiver})",
|
|
658
|
+
calcBenefitExcludedFromTotal: "excluded from total",
|
|
657
659
|
pdfCompBenefitsSection: "Compensative benefits already allocated",
|
|
658
660
|
pdfCompBenefitsItem: "Benefit",
|
|
659
661
|
pdfCompBenefitsAmount: "Value {currency}/month",
|
|
@@ -1496,6 +1498,14 @@ const defaultExpenseItems = [
|
|
|
1496
1498
|
return { label, help };
|
|
1497
1499
|
}
|
|
1498
1500
|
|
|
1501
|
+
function isLegacyLocativeExpenseLabel(label) {
|
|
1502
|
+
const normalized = String(label || "")
|
|
1503
|
+
.replace(/^[^A-Za-z\u00C0-\u024F]+/, "")
|
|
1504
|
+
.trim()
|
|
1505
|
+
.toLowerCase();
|
|
1506
|
+
return normalized === "casa (valore locativo)";
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1499
1509
|
function populateSuggestedExpenseOptions() {
|
|
1500
1510
|
const select = document.getElementById("suggestedExpenseSelect");
|
|
1501
1511
|
if (!select) return;
|
|
@@ -4638,14 +4648,14 @@ const defaultExpenseItems = [
|
|
|
4638
4648
|
const rawBenefs = Array.isArray(m.compensativeBenefits)
|
|
4639
4649
|
? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
|
|
4640
4650
|
: [];
|
|
4641
|
-
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
|
|
4651
|
+
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
|
|
4642
4652
|
const cardsHtml = benefitRows
|
|
4643
4653
|
.map((row, i) => {
|
|
4644
4654
|
const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
|
|
4645
4655
|
return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
|
|
4646
4656
|
})
|
|
4647
4657
|
.join("");
|
|
4648
|
-
const total = benefitRows
|
|
4658
|
+
const total = getCompensativeBenefitsTotal(benefitRows);
|
|
4649
4659
|
const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
|
|
4650
4660
|
resultHtml = `
|
|
4651
4661
|
<div class="spieg-no-transfer-badge">⚖️ ${escapeHtml(tr("calcNoTransferSuggested"))}</div>
|
|
@@ -4730,21 +4740,32 @@ const defaultExpenseItems = [
|
|
|
4730
4740
|
const amount = Number(row.amount || 0);
|
|
4731
4741
|
if (row.type === "family") {
|
|
4732
4742
|
const spouse = Number(row.to) === 2 ? name2 : name1;
|
|
4733
|
-
return { label: msg("calcBenefitFamilyAllowance", { spouse }), amount };
|
|
4743
|
+
return { label: msg("calcBenefitFamilyAllowance", { spouse }), amount, includeInTotal: true };
|
|
4734
4744
|
}
|
|
4735
4745
|
if (row.type === "primary-home-mortgage") {
|
|
4736
4746
|
const payer = Number(row.from) === 2 ? name2 : name1;
|
|
4737
4747
|
const receiver = Number(row.to) === 2 ? name2 : name1;
|
|
4738
|
-
return { label: msg("calcBenefitPrimaryHomeMortgage", { payer, receiver }), amount };
|
|
4748
|
+
return { label: msg("calcBenefitPrimaryHomeMortgage", { payer, receiver }), amount, includeInTotal: true };
|
|
4739
4749
|
}
|
|
4740
4750
|
if (row.type === "primary-home-assignment") {
|
|
4741
4751
|
const receiver = Number(row.to) === 2 ? name2 : name1;
|
|
4742
|
-
return {
|
|
4752
|
+
return {
|
|
4753
|
+
label: `${msg("calcBenefitPrimaryHomeAssignment", { receiver })} (${tr("calcBenefitExcludedFromTotal")})`,
|
|
4754
|
+
amount,
|
|
4755
|
+
includeInTotal: false
|
|
4756
|
+
};
|
|
4743
4757
|
}
|
|
4744
|
-
return { label: tr("calcCompBenefitsLabel"), amount };
|
|
4758
|
+
return { label: tr("calcCompBenefitsLabel"), amount, includeInTotal: true };
|
|
4745
4759
|
});
|
|
4746
4760
|
}
|
|
4747
4761
|
|
|
4762
|
+
function getCompensativeBenefitsTotal(rows) {
|
|
4763
|
+
return (rows || []).reduce((sum, row) => {
|
|
4764
|
+
if (!row || row.includeInTotal === false) return sum;
|
|
4765
|
+
return sum + Number(row.amount || 0);
|
|
4766
|
+
}, 0);
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4748
4769
|
function formatCompensativeBenefitsInline(m, name1 = c1n(), name2 = c2n()) {
|
|
4749
4770
|
return getCompensativeBenefitRows(m, name1, name2)
|
|
4750
4771
|
.map((row) => `${row.label}: ${eur(row.amount)}`)
|
|
@@ -4851,14 +4872,14 @@ const defaultExpenseItems = [
|
|
|
4851
4872
|
const rawBenefs = Array.isArray(m.compensativeBenefits)
|
|
4852
4873
|
? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
|
|
4853
4874
|
: [];
|
|
4854
|
-
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
|
|
4875
|
+
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
|
|
4855
4876
|
const cardsHtml = benefitRows
|
|
4856
4877
|
.map((row, i) => {
|
|
4857
4878
|
const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
|
|
4858
4879
|
return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
|
|
4859
4880
|
})
|
|
4860
4881
|
.join("");
|
|
4861
|
-
const total = benefitRows
|
|
4882
|
+
const total = getCompensativeBenefitsTotal(benefitRows);
|
|
4862
4883
|
const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
|
|
4863
4884
|
benefitCardsHtml = `
|
|
4864
4885
|
<div class="result-benefits-box">
|
|
@@ -5122,12 +5143,12 @@ const defaultExpenseItems = [
|
|
|
5122
5143
|
const rawBenefs = Array.isArray(m.compensativeBenefits)
|
|
5123
5144
|
? m.compensativeBenefits.filter((row) => row && Number(row.amount || 0) > 0.005)
|
|
5124
5145
|
: [];
|
|
5125
|
-
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
|
|
5146
|
+
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
|
|
5126
5147
|
const cardsHtml = compBenefits.map((row, idx) => {
|
|
5127
5148
|
const icon = (rawBenefs[idx] && typeIcons[rawBenefs[idx].type]) || "\u2726";
|
|
5128
5149
|
return `<li class="pdf-explain-benefit-card"><span class="pdf-explain-benefit-icon">${icon}</span><span class="pdf-explain-benefit-label">${escapeHtml(row.label)}</span><strong class="pdf-explain-benefit-amount">${eur(row.amount)}</strong></li>`;
|
|
5129
5150
|
}).join("");
|
|
5130
|
-
const benefitsTotal = compBenefits
|
|
5151
|
+
const benefitsTotal = getCompensativeBenefitsTotal(compBenefits);
|
|
5131
5152
|
explainResultHtml = `
|
|
5132
5153
|
<div class="pdf-explain-no-transfer-badge">⚖️ ${escapeHtml(tr("calcNoTransferSuggested"))}</div>
|
|
5133
5154
|
<div class="pdf-explain-benefits-section">
|
|
@@ -6050,6 +6071,7 @@ ${scenarioLab.length ? `
|
|
|
6050
6071
|
|
|
6051
6072
|
function hydrateState(state) {
|
|
6052
6073
|
if (!state || !state.base || !state.spese) return;
|
|
6074
|
+
let stateSpeseRows = Array.isArray(state.spese) ? state.spese : [];
|
|
6053
6075
|
Object.entries(state.base).forEach(([k, v]) => {
|
|
6054
6076
|
const el = document.getElementById(k);
|
|
6055
6077
|
if (!el) return;
|
|
@@ -6065,11 +6087,15 @@ ${scenarioLab.length ? `
|
|
|
6065
6087
|
speseConvivenzaAutoMode = Math.max(0, Number(state.base && state.base.speseConvivenza || 0)) <= 0.005;
|
|
6066
6088
|
}
|
|
6067
6089
|
if (Array.isArray(state.expenseItems) && state.expenseItems.length) {
|
|
6068
|
-
|
|
6090
|
+
const filteredPairs = state.expenseItems
|
|
6091
|
+
.map((item, idx) => ({ item, row: stateSpeseRows[idx] }))
|
|
6092
|
+
.filter((pair) => !isLegacyLocativeExpenseLabel(pair && pair.item && pair.item.label));
|
|
6093
|
+
expenseItems = filteredPairs.map((pair, idx) => normalizeExpenseItem(pair.item, idx));
|
|
6094
|
+
stateSpeseRows = filteredPairs.map((pair) => pair.row).filter((row) => row !== undefined);
|
|
6069
6095
|
} else {
|
|
6070
6096
|
expenseItems = defaultExpenseItems.map((item) => ({ ...item }));
|
|
6071
6097
|
}
|
|
6072
|
-
while (expenseItems.length <
|
|
6098
|
+
while (expenseItems.length < stateSpeseRows.length) {
|
|
6073
6099
|
expenseItems.push(normalizeExpenseItem(null, expenseItems.length));
|
|
6074
6100
|
}
|
|
6075
6101
|
scenarioLab = normalizeScenarioLabState(state.scenarioLab);
|
|
@@ -6107,7 +6133,7 @@ ${scenarioLab.length ? `
|
|
|
6107
6133
|
updateSpouseLabels();
|
|
6108
6134
|
buildExpenseRows();
|
|
6109
6135
|
syncPermanenza("calendar");
|
|
6110
|
-
|
|
6136
|
+
stateSpeseRows.forEach((row, i) => {
|
|
6111
6137
|
const c1 = document.getElementById(`c1_${i}`);
|
|
6112
6138
|
const c2 = document.getElementById(`c2_${i}`);
|
|
6113
6139
|
const d1 = document.getElementById(`c1d_${i}`);
|
package/frontend/public/app.js
CHANGED
|
@@ -295,6 +295,7 @@ const defaultExpenseItems = [
|
|
|
295
295
|
calcBenefitFamilyAllowance: "Assegno familiare INPS percepito da {spouse}",
|
|
296
296
|
calcBenefitPrimaryHomeMortgage: "Quota mutuo prima casa ceduta al collocatario ({payer} -> {receiver})",
|
|
297
297
|
calcBenefitPrimaryHomeAssignment: "Assegnazione casa familiare - valore locativo ({receiver})",
|
|
298
|
+
calcBenefitExcludedFromTotal: "fuori totale",
|
|
298
299
|
pdfCompBenefitsSection: "Benefici compensativi gia allocati",
|
|
299
300
|
pdfCompBenefitsItem: "Beneficio",
|
|
300
301
|
pdfCompBenefitsAmount: "Valore {currency}/mese",
|
|
@@ -654,6 +655,7 @@ const defaultExpenseItems = [
|
|
|
654
655
|
calcBenefitFamilyAllowance: "INPS family allowance received by {spouse}",
|
|
655
656
|
calcBenefitPrimaryHomeMortgage: "Primary-home mortgage share assigned to custodial parent ({payer} -> {receiver})",
|
|
656
657
|
calcBenefitPrimaryHomeAssignment: "Primary home assignment - rental value ({receiver})",
|
|
658
|
+
calcBenefitExcludedFromTotal: "excluded from total",
|
|
657
659
|
pdfCompBenefitsSection: "Compensative benefits already allocated",
|
|
658
660
|
pdfCompBenefitsItem: "Benefit",
|
|
659
661
|
pdfCompBenefitsAmount: "Value {currency}/month",
|
|
@@ -1496,6 +1498,14 @@ const defaultExpenseItems = [
|
|
|
1496
1498
|
return { label, help };
|
|
1497
1499
|
}
|
|
1498
1500
|
|
|
1501
|
+
function isLegacyLocativeExpenseLabel(label) {
|
|
1502
|
+
const normalized = String(label || "")
|
|
1503
|
+
.replace(/^[^A-Za-z\u00C0-\u024F]+/, "")
|
|
1504
|
+
.trim()
|
|
1505
|
+
.toLowerCase();
|
|
1506
|
+
return normalized === "casa (valore locativo)";
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1499
1509
|
function populateSuggestedExpenseOptions() {
|
|
1500
1510
|
const select = document.getElementById("suggestedExpenseSelect");
|
|
1501
1511
|
if (!select) return;
|
|
@@ -4638,14 +4648,14 @@ const defaultExpenseItems = [
|
|
|
4638
4648
|
const rawBenefs = Array.isArray(m.compensativeBenefits)
|
|
4639
4649
|
? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
|
|
4640
4650
|
: [];
|
|
4641
|
-
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
|
|
4651
|
+
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
|
|
4642
4652
|
const cardsHtml = benefitRows
|
|
4643
4653
|
.map((row, i) => {
|
|
4644
4654
|
const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
|
|
4645
4655
|
return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
|
|
4646
4656
|
})
|
|
4647
4657
|
.join("");
|
|
4648
|
-
const total = benefitRows
|
|
4658
|
+
const total = getCompensativeBenefitsTotal(benefitRows);
|
|
4649
4659
|
const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
|
|
4650
4660
|
resultHtml = `
|
|
4651
4661
|
<div class="spieg-no-transfer-badge">⚖️ ${escapeHtml(tr("calcNoTransferSuggested"))}</div>
|
|
@@ -4730,21 +4740,32 @@ const defaultExpenseItems = [
|
|
|
4730
4740
|
const amount = Number(row.amount || 0);
|
|
4731
4741
|
if (row.type === "family") {
|
|
4732
4742
|
const spouse = Number(row.to) === 2 ? name2 : name1;
|
|
4733
|
-
return { label: msg("calcBenefitFamilyAllowance", { spouse }), amount };
|
|
4743
|
+
return { label: msg("calcBenefitFamilyAllowance", { spouse }), amount, includeInTotal: true };
|
|
4734
4744
|
}
|
|
4735
4745
|
if (row.type === "primary-home-mortgage") {
|
|
4736
4746
|
const payer = Number(row.from) === 2 ? name2 : name1;
|
|
4737
4747
|
const receiver = Number(row.to) === 2 ? name2 : name1;
|
|
4738
|
-
return { label: msg("calcBenefitPrimaryHomeMortgage", { payer, receiver }), amount };
|
|
4748
|
+
return { label: msg("calcBenefitPrimaryHomeMortgage", { payer, receiver }), amount, includeInTotal: true };
|
|
4739
4749
|
}
|
|
4740
4750
|
if (row.type === "primary-home-assignment") {
|
|
4741
4751
|
const receiver = Number(row.to) === 2 ? name2 : name1;
|
|
4742
|
-
return {
|
|
4752
|
+
return {
|
|
4753
|
+
label: `${msg("calcBenefitPrimaryHomeAssignment", { receiver })} (${tr("calcBenefitExcludedFromTotal")})`,
|
|
4754
|
+
amount,
|
|
4755
|
+
includeInTotal: false
|
|
4756
|
+
};
|
|
4743
4757
|
}
|
|
4744
|
-
return { label: tr("calcCompBenefitsLabel"), amount };
|
|
4758
|
+
return { label: tr("calcCompBenefitsLabel"), amount, includeInTotal: true };
|
|
4745
4759
|
});
|
|
4746
4760
|
}
|
|
4747
4761
|
|
|
4762
|
+
function getCompensativeBenefitsTotal(rows) {
|
|
4763
|
+
return (rows || []).reduce((sum, row) => {
|
|
4764
|
+
if (!row || row.includeInTotal === false) return sum;
|
|
4765
|
+
return sum + Number(row.amount || 0);
|
|
4766
|
+
}, 0);
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4748
4769
|
function formatCompensativeBenefitsInline(m, name1 = c1n(), name2 = c2n()) {
|
|
4749
4770
|
return getCompensativeBenefitRows(m, name1, name2)
|
|
4750
4771
|
.map((row) => `${row.label}: ${eur(row.amount)}`)
|
|
@@ -4851,14 +4872,14 @@ const defaultExpenseItems = [
|
|
|
4851
4872
|
const rawBenefs = Array.isArray(m.compensativeBenefits)
|
|
4852
4873
|
? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
|
|
4853
4874
|
: [];
|
|
4854
|
-
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
|
|
4875
|
+
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
|
|
4855
4876
|
const cardsHtml = benefitRows
|
|
4856
4877
|
.map((row, i) => {
|
|
4857
4878
|
const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
|
|
4858
4879
|
return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
|
|
4859
4880
|
})
|
|
4860
4881
|
.join("");
|
|
4861
|
-
const total = benefitRows
|
|
4882
|
+
const total = getCompensativeBenefitsTotal(benefitRows);
|
|
4862
4883
|
const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
|
|
4863
4884
|
benefitCardsHtml = `
|
|
4864
4885
|
<div class="result-benefits-box">
|
|
@@ -5122,12 +5143,12 @@ const defaultExpenseItems = [
|
|
|
5122
5143
|
const rawBenefs = Array.isArray(m.compensativeBenefits)
|
|
5123
5144
|
? m.compensativeBenefits.filter((row) => row && Number(row.amount || 0) > 0.005)
|
|
5124
5145
|
: [];
|
|
5125
|
-
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
|
|
5146
|
+
const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
|
|
5126
5147
|
const cardsHtml = compBenefits.map((row, idx) => {
|
|
5127
5148
|
const icon = (rawBenefs[idx] && typeIcons[rawBenefs[idx].type]) || "\u2726";
|
|
5128
5149
|
return `<li class="pdf-explain-benefit-card"><span class="pdf-explain-benefit-icon">${icon}</span><span class="pdf-explain-benefit-label">${escapeHtml(row.label)}</span><strong class="pdf-explain-benefit-amount">${eur(row.amount)}</strong></li>`;
|
|
5129
5150
|
}).join("");
|
|
5130
|
-
const benefitsTotal = compBenefits
|
|
5151
|
+
const benefitsTotal = getCompensativeBenefitsTotal(compBenefits);
|
|
5131
5152
|
explainResultHtml = `
|
|
5132
5153
|
<div class="pdf-explain-no-transfer-badge">⚖️ ${escapeHtml(tr("calcNoTransferSuggested"))}</div>
|
|
5133
5154
|
<div class="pdf-explain-benefits-section">
|
|
@@ -6050,6 +6071,7 @@ ${scenarioLab.length ? `
|
|
|
6050
6071
|
|
|
6051
6072
|
function hydrateState(state) {
|
|
6052
6073
|
if (!state || !state.base || !state.spese) return;
|
|
6074
|
+
let stateSpeseRows = Array.isArray(state.spese) ? state.spese : [];
|
|
6053
6075
|
Object.entries(state.base).forEach(([k, v]) => {
|
|
6054
6076
|
const el = document.getElementById(k);
|
|
6055
6077
|
if (!el) return;
|
|
@@ -6065,11 +6087,15 @@ ${scenarioLab.length ? `
|
|
|
6065
6087
|
speseConvivenzaAutoMode = Math.max(0, Number(state.base && state.base.speseConvivenza || 0)) <= 0.005;
|
|
6066
6088
|
}
|
|
6067
6089
|
if (Array.isArray(state.expenseItems) && state.expenseItems.length) {
|
|
6068
|
-
|
|
6090
|
+
const filteredPairs = state.expenseItems
|
|
6091
|
+
.map((item, idx) => ({ item, row: stateSpeseRows[idx] }))
|
|
6092
|
+
.filter((pair) => !isLegacyLocativeExpenseLabel(pair && pair.item && pair.item.label));
|
|
6093
|
+
expenseItems = filteredPairs.map((pair, idx) => normalizeExpenseItem(pair.item, idx));
|
|
6094
|
+
stateSpeseRows = filteredPairs.map((pair) => pair.row).filter((row) => row !== undefined);
|
|
6069
6095
|
} else {
|
|
6070
6096
|
expenseItems = defaultExpenseItems.map((item) => ({ ...item }));
|
|
6071
6097
|
}
|
|
6072
|
-
while (expenseItems.length <
|
|
6098
|
+
while (expenseItems.length < stateSpeseRows.length) {
|
|
6073
6099
|
expenseItems.push(normalizeExpenseItem(null, expenseItems.length));
|
|
6074
6100
|
}
|
|
6075
6101
|
scenarioLab = normalizeScenarioLabState(state.scenarioLab);
|
|
@@ -6107,7 +6133,7 @@ ${scenarioLab.length ? `
|
|
|
6107
6133
|
updateSpouseLabels();
|
|
6108
6134
|
buildExpenseRows();
|
|
6109
6135
|
syncPermanenza("calendar");
|
|
6110
|
-
|
|
6136
|
+
stateSpeseRows.forEach((row, i) => {
|
|
6111
6137
|
const c1 = document.getElementById(`c1_${i}`);
|
|
6112
6138
|
const c2 = document.getElementById(`c2_${i}`);
|
|
6113
6139
|
const d1 = document.getElementById(`c1d_${i}`);
|
|
@@ -885,21 +885,60 @@
|
|
|
885
885
|
}
|
|
886
886
|
|
|
887
887
|
.extra-box-first-home {
|
|
888
|
+
position: relative;
|
|
889
|
+
overflow: hidden;
|
|
888
890
|
background: linear-gradient(135deg, #ffffff 0%, #f0fffe 50%, #f5faff 100%);
|
|
889
891
|
border: 1px solid rgba(27, 141, 127, 0.15);
|
|
890
892
|
box-shadow: 0 2px 8px rgba(27, 141, 127, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
|
891
893
|
}
|
|
892
894
|
|
|
895
|
+
.extra-box-first-home::after {
|
|
896
|
+
content: "";
|
|
897
|
+
position: absolute;
|
|
898
|
+
inset: -40% -20% auto;
|
|
899
|
+
height: 180px;
|
|
900
|
+
background: radial-gradient(circle at 50% 50%, rgba(61, 181, 160, 0.16), rgba(216, 154, 53, 0.08) 45%, transparent 70%);
|
|
901
|
+
pointer-events: none;
|
|
902
|
+
animation: first-home-aurora 7s ease-in-out infinite alternate;
|
|
903
|
+
}
|
|
904
|
+
|
|
893
905
|
.extra-box-first-home .extra-box-title::before {
|
|
894
906
|
content: '🏠 ';
|
|
895
907
|
margin-right: 4px;
|
|
896
908
|
}
|
|
897
909
|
|
|
898
910
|
.extra-box-first-home .extra-grid {
|
|
911
|
+
position: relative;
|
|
912
|
+
z-index: 1;
|
|
899
913
|
gap: 8px 10px;
|
|
900
914
|
}
|
|
901
915
|
|
|
916
|
+
.extra-box-first-home .field {
|
|
917
|
+
transition: transform 0.2s ease, filter 0.2s ease;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
.extra-box-first-home .field:focus-within {
|
|
921
|
+
transform: translateY(-1px);
|
|
922
|
+
filter: saturate(1.04);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
.extra-box-first-home .field input[type="number"],
|
|
926
|
+
.extra-box-first-home .field select {
|
|
927
|
+
border-width: 1.5px;
|
|
928
|
+
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8) inset;
|
|
929
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
.extra-box-first-home .field input[type="number"]:focus,
|
|
933
|
+
.extra-box-first-home .field select:focus {
|
|
934
|
+
border-color: rgba(27, 141, 127, 0.4);
|
|
935
|
+
box-shadow: 0 0 0 3px rgba(27, 141, 127, 0.14), 0 1px 0 rgba(255, 255, 255, 0.85) inset;
|
|
936
|
+
background: linear-gradient(180deg, #ffffff, #f4fffd);
|
|
937
|
+
}
|
|
938
|
+
|
|
902
939
|
.mortgage-split-slider {
|
|
940
|
+
position: relative;
|
|
941
|
+
overflow: hidden;
|
|
903
942
|
margin-top: 12px;
|
|
904
943
|
border: 1.5px solid rgba(27, 141, 127, 0.2);
|
|
905
944
|
border-radius: 16px;
|
|
@@ -916,11 +955,25 @@
|
|
|
916
955
|
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
917
956
|
}
|
|
918
957
|
|
|
958
|
+
.mortgage-split-slider::after {
|
|
959
|
+
content: "";
|
|
960
|
+
position: absolute;
|
|
961
|
+
inset: 0;
|
|
962
|
+
background: linear-gradient(112deg, transparent 30%, rgba(255, 255, 255, 0.55) 46%, transparent 58%);
|
|
963
|
+
transform: translateX(-120%);
|
|
964
|
+
transition: transform 0.5s ease;
|
|
965
|
+
pointer-events: none;
|
|
966
|
+
}
|
|
967
|
+
|
|
919
968
|
.mortgage-split-slider:hover {
|
|
920
969
|
box-shadow: 0 8px 20px rgba(27, 141, 127, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
|
921
970
|
border-color: rgba(27, 141, 127, 0.3);
|
|
922
971
|
}
|
|
923
972
|
|
|
973
|
+
.mortgage-split-slider:hover::after {
|
|
974
|
+
transform: translateX(120%);
|
|
975
|
+
}
|
|
976
|
+
|
|
924
977
|
.mortgage-split-slider.is-disabled {
|
|
925
978
|
opacity: 0.55;
|
|
926
979
|
filter: grayscale(0.4);
|
|
@@ -1098,6 +1151,17 @@
|
|
|
1098
1151
|
box-shadow: 0 2px 6px rgba(27, 141, 127, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.6);
|
|
1099
1152
|
transition: all 0.2s ease;
|
|
1100
1153
|
letter-spacing: 0.2px;
|
|
1154
|
+
animation: split-center-breathe 2.6s ease-in-out infinite;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
@keyframes first-home-aurora {
|
|
1158
|
+
0% { transform: translate3d(-5%, -12%, 0) scale(1); }
|
|
1159
|
+
100% { transform: translate3d(6%, -6%, 0) scale(1.08); }
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
@keyframes split-center-breathe {
|
|
1163
|
+
0%, 100% { box-shadow: 0 2px 6px rgba(27, 141, 127, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.6); }
|
|
1164
|
+
50% { box-shadow: 0 5px 14px rgba(27, 141, 127, 0.24), inset 0 1px 2px rgba(255, 255, 255, 0.75); }
|
|
1101
1165
|
}
|
|
1102
1166
|
|
|
1103
1167
|
#primaCasaMutuoSplitInfo {
|