// Generated, do not edit. sha256:6eef7930e5d81c104d37fffaf0d8f5c9109485ed27fb20ffaaecdf946a306931 import { scheduleForecast, dueCreditsForAccount, dueCreditsAll, bookDueCredit, dismissDueCredit } from '../data/interest-credits.js'; import { byPeriod, bookableDues, dueKey } from './interest-order.js'; import { listSchedulesForAccount } from '../data/interest-schedules.js'; import { t } from '../i18n/index.js'; import * as dialog from '../ui/dialog.js'; import { fmtUnit, val, pct } from '../ui/format.js'; import { taskCardHtml, nothingPendingHtml } from '../ui/task-card.js'; import { esc } from '../ui/escape.js'; import { CHEVRON } from '../ui/icons.js'; import { expanders } from '../ui/expand.js'; const dueMeta = d => ({ decimals: d.payout_decimals, unit: d.payout_unit, subunit: d.payout_subunit, displayUnit: d.payout_display_unit }); const dueKnoppen = (i, kan) => `` + ``; const dueUitleg = (due, boekbaar) => due.some(d => !boekbaar.has(dueKey(d))) ? `
${t('accounts.bookOldestFirst')}
` : ''; function wireDue(scopeEl, due, refresh) { scopeEl.querySelectorAll('[data-book]').forEach(b => b.onclick = async () => { const d = due[Number(b.dataset.book)]; const amt = `${fmtUnit(d.projected_sub, dueMeta(d))}`; if (!(await dialog.confirm({ message: `${t('accounts.confirmBook')} ${amt} (${d.periodStart} → ${d.periodEnd})?` }))) return; try { await bookDueCredit(d, d.projected_sub); refresh(); } catch (e) { dialog.alert({ title: t('dialog.error'), message: e.message }); } }); scopeEl.querySelectorAll('[data-dismiss]').forEach(b => b.onclick = async () => { const d = due[Number(b.dataset.dismiss)]; try { await dismissDueCredit(d); refresh(); } catch (e) { dialog.alert({ title: t('dialog.error'), message: e.message }); } }); } const fig = (label, value, sub = '') => `
${label}
` + `
${value}
${sub ? `
${sub}
` : ''}
`; export async function renderScheduleStatus(statusHost, accountId, refresh) { if (!statusHost) return false; const today = new Date().toISOString().slice(0, 10); const scheds = (await listSchedulesForAccount(accountId)).filter(s => s.rateKind === 'fixed' && (!s.endsOn || s.endsOn >= today)); const due = byPeriod(await dueCreditsForAccount(accountId)); const boekbaar = bookableDues(due); const prognoses = await Promise.all(scheds.map(s => scheduleForecast(s))); const expand = await expanders('interest', { upcoming: false }); const projHtml = scheds.map((s, i) => { const f = prognoses[i]; const m = { decimals: s.payout_decimals, unit: s.payout_unit, subunit: s.payout_subunit, displayUnit: s.payout_display_unit }; const pm = { decimals: s.principal_decimals, unit: s.principal_unit, subunit: s.principal_subunit, displayUnit: s.principal_display_unit }; const asset = s.principal_symbol === s.payout_symbol ? esc(s.payout_symbol) : `${esc(s.principal_symbol)} → ${esc(s.payout_symbol)}`; const naam = s.note ? esc(s.note) : asset; const termen = [ ...(s.note ? [asset] : []), pct(s.annualRate), s.principalAmount != null ? t('accounts.projOver', { bedrag: val(fmtUnit(s.principalAmount, pm)) }) : t('interest.principalFollowsBalance'), t('enums.interest_cadence.' + s.creditCadence), s.endsOn ? t('accounts.projUntil', { datum: esc(s.endsOn) }) : t('interest.endsOnOpen'), ].join(' · '); const volgende = f.upcoming[0]; const cijfers = [ fig(t('accounts.projReceived'), val(fmtUnit(f.realizedSub, m))), ...(f.termTotalSub != null ? [ fig(t('accounts.projExpectRemain'), val(fmtUnit(f.remainingSub, m)), t('accounts.projCount', { n: f.remainingCount })), fig(t('accounts.projTermTotal'), val(fmtUnit(f.termTotalSub, m))), ] : []), ...(f.termTotalSub != null && f.sameAsset ? [ fig(t('accounts.projEndBalance', { datum: esc(s.endsOn) }), val(fmtUnit(s.principalAmount + f.termTotalSub, m)), t('accounts.projEndBalanceSub')), ] : []), ...(volgende ? [fig(t('accounts.projNext'), val(fmtUnit(volgende.projectedSub, m)), esc(volgende.periodEnd))] : []), ].join(''); const komend = f.upcoming.length > 1 ? `
${t('accounts.projAllUpcoming', { n: f.upcoming.length })}` + `` + `
${f.upcoming.map(p => `
${esc(p.periodEnd)}` + `${val(fmtUnit(p.projectedSub, m))}
`).join('')}
` : ''; return `
${naam}` + `${termen}
${cijfers}
${komend}
`; }).join(''); const dueHtml = due.length ? `
${t('accounts.dueTitle')}
` + due.map((d, i) => `
` + `${d.periodStart} → ${d.periodEnd}${val(fmtUnit(d.projected_sub, dueMeta(d)))}` + `${dueKnoppen(i, boekbaar.has(dueKey(d)))}
`).join('') + dueUitleg(due, boekbaar) + '
' : ''; statusHost.innerHTML = projHtml + dueHtml; expand.bind(statusHost); statusHost.querySelectorAll('.ip-upcoming').forEach(d => d.addEventListener('toggle', () => { document.querySelectorAll('.ip-upcoming').forEach(o => { if (o.open !== d.open) o.open = d.open; }); })); wireDue(statusHost, due, refresh); return Boolean(projHtml || dueHtml); } export async function renderInterestWidget(host, refresh) { const due = byPeriod(await dueCreditsAll()); const boekbaar = bookableDues(due); const body = due.length === 0 ? nothingPendingHtml() : due.map((d, i) => `
` + `${esc(d.account_name)} · ${d.periodStart} → ${d.periodEnd}: ${val(fmtUnit(d.projected_sub, dueMeta(d)))}` + `${dueKnoppen(i, boekbaar.has(dueKey(d)))}
`).join('') + dueUitleg(due, boekbaar); host.innerHTML = taskCardHtml({ title: t('actions.interestTitle'), body }); wireDue(host, due, refresh); return due.length; }