// Generated, do not edit. sha256:877ef362c70027a6a3b598d45680633fae5e6da42177c2b820d61d28df5d8d58 import { listSelectableAccounts } from '../data/accounts.js'; import { listBookableAssets } from '../data/assets.js'; import { createReservation, deleteReservation, listReservations, listReservationsForAccount, updateReservation } from '../data/reservations.js'; import { tableViewCfg } from '../data/preferences.js'; import { t } from '../i18n/index.js'; import { assetLabelHtml } from '../ui/asset-label.js'; import * as dialog from '../ui/dialog.js'; import { renderTable } from '../ui/table.js'; import { takeRowFocus } from '../ui/row-focus.js'; import { fmtUnit, val, toSubunit, fromSubunit } from '../ui/format.js'; import { esc } from '../ui/escape.js'; import { setPageHint } from '../ui/page-hint.js'; import { localDate, localDateNl, toUtcIso } from '../../shared/time.js'; import { bookReservationFlow, reservationAccount, reservationDir, reservationMeta } from '../actions/reservation-book.js'; export async function render(el, { accountId = null, assetId = null, assetKinds = null } = {}) { el.innerHTML = `
`; const onPage = accountId == null; if (onPage) setPageHint(el, { title: t('nav.reservations'), rows: [t('reservations.hint')] }); const allowed = a => (assetId == null || a.id === assetId) && (assetKinds == null || assetKinds.includes(a.kind)); const assets = (await listBookableAssets()).filter(allowed); const assetById = id => assets.find(a => a.id === Number(id)); const rows = async () => (onPage ? await listReservations() : await listReservationsForAccount(accountId)) .filter(r => assetId == null || r.assetId === assetId); const now = new Date().toISOString(); const dirLabel = d => t(d === 'out' ? 'reservations.dirOut' : 'reservations.dirIn'); const accountOpts = async current => (await listSelectableAccounts({ ookId: Number(current) || null })) .map(a => ({ value: a.id, label: a.name })); const columns = [ { key: 'occurredAt', label: t('reservations.colDate'), sortable: true, render: r => `${esc(localDateNl(r.occurredAt))}${r.occurredAt <= now ? ` ${t('reservations.due')}` : ''}`, edit: { type: 'date', value: r => (r ? localDate(r.occurredAt) : localDate(now)) } }, ...(onPage ? [{ key: '_account', label: t('reservations.colAccount'), sortable: true, sortValue: r => reservationAccount(r).name || '', render: r => esc(reservationAccount(r).name || '-'), group: { value: r => reservationAccount(r).name || '-', label: v => v }, edit: { type: 'select', sticky: true, value: r => (r ? reservationAccount(r).id : ''), options: vals => accountOpts(vals._account) } }] : []), { key: '_dir', label: t('reservations.colDirection'), sortable: true, sortValue: r => reservationDir(r), render: r => dirLabel(reservationDir(r)), edit: { type: 'select', sticky: true, value: r => (r ? reservationDir(r) : 'out'), options: () => [{ value: 'out', label: dirLabel('out') }, { value: 'in', label: dirLabel('in') }] } }, { key: 'assetId', label: t('reservations.colAsset'), sortable: true, sortValue: r => r.asset_symbol, render: r => assetLabelHtml(r), edit: { type: 'select', sticky: true, options: () => assets.map(a => ({ value: a.id, label: `${a.symbol}: ${a.name}` })) } }, { key: 'amount', label: t('reservations.colAmount'), align: 'num', sortable: true, sortValue: r => r.amount, render: r => val(fmtUnit(r.amount, reservationMeta(r))), edit: { type: 'number', attrs: { min: 0, step: 'any' }, value: r => (r ? fromSubunit(r.amount, reservationMeta(r)) : '') } }, { key: 'note', label: t('reservations.colNote'), text: true, render: r => `${esc(r.note || '')}`, edit: { type: 'text', expand: true } }, ]; const toPayload = v => { const asset = assetById(v.assetId); const qty = parseFloat(v.amount); const account = onPage ? Number(v._account) || null : accountId; if (!v.occurredAt || !asset || !account || !Number.isFinite(qty) || qty <= 0) throw new Error(t('reservations.fill')); return { accountId: account, assetId: asset.id, direction: v._dir === 'in' ? 'in' : 'out', amount: toSubunit(qty, asset), occurredAt: toUtcIso(`${v.occurredAt}T00:00:00`), note: (v.note || '').trim() || null, }; }; let tableApi = null; const reload = async () => tableApi.refresh(await rows()); tableApi = renderTable(el.querySelector('#tbl'), { columns, rows: await rows(), ...(await tableViewCfg('reservations', { key: 'occurredAt', dir: 'asc' })), emptyText: t(onPage ? 'reservations.noneAll' : 'reservations.none'), noneLabel: t('table.none'), newLabel: t('table.new'), newDefaults: { _dir: 'out', assetId: assets[0]?.id ?? '', note: '' }, saveLabel: t('transfers.save'), cancelLabel: t('transfers.cancel'), onCreate: async v => { const id = await createReservation(toPayload(v)); tableApi.refresh(await rows(), { locate: id }); }, onSave: async (id, v) => { await updateReservation(id, toPayload(v)); reload(); }, onDelete: async id => { if (!(await dialog.confirm({ message: t('reservations.confirmDelete'), danger: true }))) return; await deleteReservation(id); reload(); }, extraActions: [{ key: 'book', label: t('reservations.book') }], onAction: async (key, id) => { const r = (await rows()).find(x => x.id === id); if (key === 'book' && r && await bookReservationFlow(r)) reload(); }, }); tableApi.focusRow(takeRowFocus('reservations')); }