mantenimento-app 2.2.4 → 2.2.5

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
@@ -4820,7 +4820,7 @@ const defaultExpenseItems = [
4820
4820
  const el = document.getElementById(`${spouseKey}d_${idx}`);
4821
4821
  const raw = String(el && el.value ? el.value : "").trim();
4822
4822
  if (!raw) return "";
4823
- return `${escapeHtml(raw)} <span class="expense-detail-meta">(${raw.length}/${EXPENSE_DETAIL_MAX_CHARS})</span>`;
4823
+ return `${escapeHtml(raw)}`;
4824
4824
  };
4825
4825
  const speseRowsBase = expenseItems.map((item, i) => {
4826
4826
  const c1 = num(`c1_${i}`);
@@ -4956,6 +4956,48 @@ const defaultExpenseItems = [
4956
4956
  const scenarioSectionClass = scenarioLab.length >= 3
4957
4957
  ? "section scenario-section compact-3"
4958
4958
  : "section scenario-section";
4959
+ const scenarioSavedTitle = currentLang === "en" ? "Saved scenarios overview" : "Quadro scenari salvati";
4960
+ const scenarioActiveLabel = currentLang === "en" ? "selected" : "selezionato";
4961
+ const scenarioSupportLabel = currentLang === "en" ? "Support" : "Assegno";
4962
+ const scenarioNeedsLabel = currentLang === "en" ? "Children needs" : "Fabbisogno figli";
4963
+ const scenarioPostLabel = currentLang === "en" ? "Post-support" : "Post-assegno";
4964
+ const scenarioCardsHtml = scenarioLab.length
4965
+ ? `<div class="scenario-mini-grid">${scenarioLab.map((scenario, idx) => {
4966
+ const sm = scenario.model || computeModelLocal(scenario.payload || {});
4967
+ const s1 = escapeHtml(String((scenario.payload && scenario.payload._nome1) || c1Name || tr("spouse1Default")));
4968
+ const s2 = escapeHtml(String((scenario.payload && scenario.payload._nome2) || c2Name || tr("spouse2Default")));
4969
+ const modeTxt = escapeHtml(getModeName(sm.mode, sm.simplePerc));
4970
+ const support = eur(Math.max(sm.assegnoDa1a2 || 0, sm.assegnoDa2a1 || 0));
4971
+ const selectedChip = idx === selectedScenarioIdx ? `<span class="scenario-mini-selected">${escapeHtml(scenarioActiveLabel)}</span>` : "";
4972
+ return `<div class="scenario-mini-card">
4973
+ <div class="scenario-mini-head"><span class="scenario-chip">Sc ${escapeHtml(scenario.label || SCENARIO_LABELS[idx] || String(idx + 1))}</span>${selectedChip}</div>
4974
+ <div class="scenario-mini-meta">${s1} / ${s2}</div>
4975
+ <div class="scenario-mini-mode">${modeTxt}</div>
4976
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioSupportLabel)}</span><strong>${support}</strong></div>
4977
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioNeedsLabel)}</span><strong>${eur(sm.fabbisognoFigli || 0)}</strong></div>
4978
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioPostLabel)} ${s1}</span><strong>${eur(sm.post1 || 0)}</strong></div>
4979
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioPostLabel)} ${s2}</span><strong>${eur(sm.post2 || 0)}</strong></div>
4980
+ </div>`;
4981
+ }).join("")}</div>`
4982
+ : "";
4983
+ const separationSectionHtml = m.speseConvivenza > 0
4984
+ ? `
4985
+ <div class="section">
4986
+ <div class="section-title">${tr("sepCostPanelTitle")}</div>
4987
+ <table>
4988
+ <tbody>
4989
+ <tr><td>${tr("sepCostNetTogether")}</td><td class="num"><strong>${eur(m.nettoInsiemeCombinato || 0)}</strong></td></tr>
4990
+ <tr><td>${tr("sepCostNetSeparated")}</td><td class="num"><strong>${eur(m.nettoSeparatoTotale || 0)}</strong></td></tr>
4991
+ ${m.separationAdjustmentHousingUtilities > 0 ? `<tr><td>${tr("sepCostHousingUtilityAdj")}</td><td class="num">${eur(m.separationAdjustmentHousingUtilities)}</td></tr>` : ""}
4992
+ <tr><td>${tr("sepCostDuplication")}</td><td class="num"><strong>${eur(m.costoSeparazioneMensile || 0)}</strong></td></tr>
4993
+ <tr><td>${tr("sepCostLossMonthly")}</td><td class="num"><strong>${eur(m.perditaMensile || 0)}</strong></td></tr>
4994
+ <tr><td>${tr("sepCostLossAnnually")}</td><td class="num"><strong>${eur(m.perditaAnnua || 0)}</strong></td></tr>
4995
+ <tr><td>${msg("sepCostLossSpouse", { spouse: c1NameEsc })}</td><td class="num">${eur(m.perditaSpouse1 || 0)}</td></tr>
4996
+ <tr><td>${msg("sepCostLossSpouse", { spouse: c2NameEsc })}</td><td class="num">${eur(m.perditaSpouse2 || 0)}</td></tr>
4997
+ </tbody>
4998
+ </table>
4999
+ </div>`
5000
+ : "";
4959
5001
 
4960
5002
  const html = `<!DOCTYPE html>
4961
5003
  <html lang="${pdfLang}">
@@ -5082,6 +5124,14 @@ const defaultExpenseItems = [
5082
5124
 
5083
5125
  /* ── SCENARIO LAB ── */
5084
5126
  .scenario-compare-wrap { overflow-x: auto; }
5127
+ .scenario-mini-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 8px; margin-bottom: 10px; }
5128
+ .scenario-mini-card { border: 1px solid #c6ddd8; border-radius: 8px; background: #f7fcfb; padding: 7px 8px; }
5129
+ .scenario-mini-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 3px; }
5130
+ .scenario-mini-selected { font-size: 6.7pt; color: #0f6a61; font-weight: 700; border: 1px solid #a9d4c0; border-radius: 999px; padding: 0 6px; background: #eaf7f1; }
5131
+ .scenario-mini-meta { font-size: 7.1pt; color: #4c6964; margin-bottom: 2px; }
5132
+ .scenario-mini-mode { font-size: 7.2pt; font-weight: 700; color: #183d39; margin-bottom: 5px; }
5133
+ .scenario-mini-row { display: flex; justify-content: space-between; gap: 8px; font-size: 7.4pt; padding: 1px 0; }
5134
+ .scenario-mini-row strong { font-variant-numeric: tabular-nums; }
5085
5135
  .scenario-compare-table { width: 100%; border-collapse: collapse; font-size: 8.5pt; }
5086
5136
  .scenario-compare-table th, .scenario-compare-table td { border: 1px solid #c6ddd8; padding: 5px 8px; }
5087
5137
  .scenario-compare-table thead th { background: linear-gradient(90deg,#f0f7f5,#e6f1ee); color: #183d39; font-weight: 700; }
@@ -5385,6 +5435,8 @@ const defaultExpenseItems = [
5385
5435
  </div>
5386
5436
  </div>
5387
5437
 
5438
+ ${separationSectionHtml}
5439
+
5388
5440
  <div class="section">
5389
5441
  <div class="section-title">${tr("spiegTitle")}</div>
5390
5442
  <div class="pdf-explain-grid">
@@ -5419,6 +5471,8 @@ const defaultExpenseItems = [
5419
5471
  ${scenarioLab.length ? `
5420
5472
  <div class="${scenarioSectionClass}">
5421
5473
  <div class="section-title">${tr("pdfScenarioSection")}</div>
5474
+ <div style="font-size:8pt;font-weight:700;color:#1a4e49;margin-bottom:6px;">${escapeHtml(scenarioSavedTitle)}</div>
5475
+ ${scenarioCardsHtml}
5422
5476
  ${scenarioPdfTable}
5423
5477
  </div>
5424
5478
  ` : ""}
@@ -4820,7 +4820,7 @@ const defaultExpenseItems = [
4820
4820
  const el = document.getElementById(`${spouseKey}d_${idx}`);
4821
4821
  const raw = String(el && el.value ? el.value : "").trim();
4822
4822
  if (!raw) return "";
4823
- return `${escapeHtml(raw)} <span class="expense-detail-meta">(${raw.length}/${EXPENSE_DETAIL_MAX_CHARS})</span>`;
4823
+ return `${escapeHtml(raw)}`;
4824
4824
  };
4825
4825
  const speseRowsBase = expenseItems.map((item, i) => {
4826
4826
  const c1 = num(`c1_${i}`);
@@ -4956,6 +4956,48 @@ const defaultExpenseItems = [
4956
4956
  const scenarioSectionClass = scenarioLab.length >= 3
4957
4957
  ? "section scenario-section compact-3"
4958
4958
  : "section scenario-section";
4959
+ const scenarioSavedTitle = currentLang === "en" ? "Saved scenarios overview" : "Quadro scenari salvati";
4960
+ const scenarioActiveLabel = currentLang === "en" ? "selected" : "selezionato";
4961
+ const scenarioSupportLabel = currentLang === "en" ? "Support" : "Assegno";
4962
+ const scenarioNeedsLabel = currentLang === "en" ? "Children needs" : "Fabbisogno figli";
4963
+ const scenarioPostLabel = currentLang === "en" ? "Post-support" : "Post-assegno";
4964
+ const scenarioCardsHtml = scenarioLab.length
4965
+ ? `<div class="scenario-mini-grid">${scenarioLab.map((scenario, idx) => {
4966
+ const sm = scenario.model || computeModelLocal(scenario.payload || {});
4967
+ const s1 = escapeHtml(String((scenario.payload && scenario.payload._nome1) || c1Name || tr("spouse1Default")));
4968
+ const s2 = escapeHtml(String((scenario.payload && scenario.payload._nome2) || c2Name || tr("spouse2Default")));
4969
+ const modeTxt = escapeHtml(getModeName(sm.mode, sm.simplePerc));
4970
+ const support = eur(Math.max(sm.assegnoDa1a2 || 0, sm.assegnoDa2a1 || 0));
4971
+ const selectedChip = idx === selectedScenarioIdx ? `<span class="scenario-mini-selected">${escapeHtml(scenarioActiveLabel)}</span>` : "";
4972
+ return `<div class="scenario-mini-card">
4973
+ <div class="scenario-mini-head"><span class="scenario-chip">Sc ${escapeHtml(scenario.label || SCENARIO_LABELS[idx] || String(idx + 1))}</span>${selectedChip}</div>
4974
+ <div class="scenario-mini-meta">${s1} / ${s2}</div>
4975
+ <div class="scenario-mini-mode">${modeTxt}</div>
4976
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioSupportLabel)}</span><strong>${support}</strong></div>
4977
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioNeedsLabel)}</span><strong>${eur(sm.fabbisognoFigli || 0)}</strong></div>
4978
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioPostLabel)} ${s1}</span><strong>${eur(sm.post1 || 0)}</strong></div>
4979
+ <div class="scenario-mini-row"><span>${escapeHtml(scenarioPostLabel)} ${s2}</span><strong>${eur(sm.post2 || 0)}</strong></div>
4980
+ </div>`;
4981
+ }).join("")}</div>`
4982
+ : "";
4983
+ const separationSectionHtml = m.speseConvivenza > 0
4984
+ ? `
4985
+ <div class="section">
4986
+ <div class="section-title">${tr("sepCostPanelTitle")}</div>
4987
+ <table>
4988
+ <tbody>
4989
+ <tr><td>${tr("sepCostNetTogether")}</td><td class="num"><strong>${eur(m.nettoInsiemeCombinato || 0)}</strong></td></tr>
4990
+ <tr><td>${tr("sepCostNetSeparated")}</td><td class="num"><strong>${eur(m.nettoSeparatoTotale || 0)}</strong></td></tr>
4991
+ ${m.separationAdjustmentHousingUtilities > 0 ? `<tr><td>${tr("sepCostHousingUtilityAdj")}</td><td class="num">${eur(m.separationAdjustmentHousingUtilities)}</td></tr>` : ""}
4992
+ <tr><td>${tr("sepCostDuplication")}</td><td class="num"><strong>${eur(m.costoSeparazioneMensile || 0)}</strong></td></tr>
4993
+ <tr><td>${tr("sepCostLossMonthly")}</td><td class="num"><strong>${eur(m.perditaMensile || 0)}</strong></td></tr>
4994
+ <tr><td>${tr("sepCostLossAnnually")}</td><td class="num"><strong>${eur(m.perditaAnnua || 0)}</strong></td></tr>
4995
+ <tr><td>${msg("sepCostLossSpouse", { spouse: c1NameEsc })}</td><td class="num">${eur(m.perditaSpouse1 || 0)}</td></tr>
4996
+ <tr><td>${msg("sepCostLossSpouse", { spouse: c2NameEsc })}</td><td class="num">${eur(m.perditaSpouse2 || 0)}</td></tr>
4997
+ </tbody>
4998
+ </table>
4999
+ </div>`
5000
+ : "";
4959
5001
 
4960
5002
  const html = `<!DOCTYPE html>
4961
5003
  <html lang="${pdfLang}">
@@ -5082,6 +5124,14 @@ const defaultExpenseItems = [
5082
5124
 
5083
5125
  /* ── SCENARIO LAB ── */
5084
5126
  .scenario-compare-wrap { overflow-x: auto; }
5127
+ .scenario-mini-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 8px; margin-bottom: 10px; }
5128
+ .scenario-mini-card { border: 1px solid #c6ddd8; border-radius: 8px; background: #f7fcfb; padding: 7px 8px; }
5129
+ .scenario-mini-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 3px; }
5130
+ .scenario-mini-selected { font-size: 6.7pt; color: #0f6a61; font-weight: 700; border: 1px solid #a9d4c0; border-radius: 999px; padding: 0 6px; background: #eaf7f1; }
5131
+ .scenario-mini-meta { font-size: 7.1pt; color: #4c6964; margin-bottom: 2px; }
5132
+ .scenario-mini-mode { font-size: 7.2pt; font-weight: 700; color: #183d39; margin-bottom: 5px; }
5133
+ .scenario-mini-row { display: flex; justify-content: space-between; gap: 8px; font-size: 7.4pt; padding: 1px 0; }
5134
+ .scenario-mini-row strong { font-variant-numeric: tabular-nums; }
5085
5135
  .scenario-compare-table { width: 100%; border-collapse: collapse; font-size: 8.5pt; }
5086
5136
  .scenario-compare-table th, .scenario-compare-table td { border: 1px solid #c6ddd8; padding: 5px 8px; }
5087
5137
  .scenario-compare-table thead th { background: linear-gradient(90deg,#f0f7f5,#e6f1ee); color: #183d39; font-weight: 700; }
@@ -5385,6 +5435,8 @@ const defaultExpenseItems = [
5385
5435
  </div>
5386
5436
  </div>
5387
5437
 
5438
+ ${separationSectionHtml}
5439
+
5388
5440
  <div class="section">
5389
5441
  <div class="section-title">${tr("spiegTitle")}</div>
5390
5442
  <div class="pdf-explain-grid">
@@ -5419,6 +5471,8 @@ const defaultExpenseItems = [
5419
5471
  ${scenarioLab.length ? `
5420
5472
  <div class="${scenarioSectionClass}">
5421
5473
  <div class="section-title">${tr("pdfScenarioSection")}</div>
5474
+ <div style="font-size:8pt;font-weight:700;color:#1a4e49;margin-bottom:6px;">${escapeHtml(scenarioSavedTitle)}</div>
5475
+ ${scenarioCardsHtml}
5422
5476
  ${scenarioPdfTable}
5423
5477
  </div>
5424
5478
  ` : ""}
@@ -599,7 +599,7 @@
599
599
  <script src="supabase.min.js"></script>
600
600
  <script src="fabric.min.js"></script>
601
601
  <script src="html2pdf.bundle.min.js"></script>
602
- <script src="app.js?v=2.2.4"></script>
602
+ <script src="app.js?v=2.2.5"></script>
603
603
  </body>
604
604
  </html>
605
605
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mantenimento-app",
3
- "version": "2.2.4",
3
+ "version": "2.2.5",
4
4
  "description": "Frontend + backend architecture for the mantenimento calculator",
5
5
  "type": "commonjs",
6
6
  "main": "backend/calculate-model.js",