Files

43 lines
2.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(() => {
const modal = document.querySelector('#detailModal');
const viewport = document.querySelector('#modalViewport');
const renderCharts = root => root.querySelectorAll('[data-chart]').forEach(host => {
if (host.dataset.rendered) return;
host.dataset.rendered = 'true';
const data = JSON.parse(host.dataset.chart);
const render = (title, series, color, unit = 'тыс. руб.') => {
const width = 520, height = 252, pad = {l: 42, r: 18, t: 18, b: 36};
const values = series.map(item => item.value), maximum = Math.max(...values) * 1.15, minimum = Math.min(0, ...values) * .85;
const x = index => pad.l + index * ((width - pad.l - pad.r) / Math.max(1, series.length - 1));
const y = value => pad.t + (maximum - value) / (maximum - minimum || 1) * (height - pad.t - pad.b);
const points = series.map((item, index) => `${x(index)},${y(item.value)}`).join(' ');
const area = `${pad.l},${height - pad.b} ${points} ${x(series.length - 1)},${height - pad.b}`;
const grid = [0, .25, .5, .75, 1].map(t => { const yy = pad.t + t * (height - pad.t - pad.b); return `<line class="grid-line" x1="${pad.l}" y1="${yy}" x2="${width-pad.r}" y2="${yy}"/>`; }).join('');
const labels = series.map((item, index) => `<text class="chart-label" x="${x(index)}" y="${height-12}" text-anchor="middle">${item.year}</text>`).join('');
const dots = series.map((item, index) => `<circle class="chart-point" cx="${x(index)}" cy="${y(item.value)}" r="5"><title>${item.year}: ${item.value.toLocaleString('ru-RU')} ${unit}</title></circle>`).join('');
return `<article class="line-chart" style="--chart:${color}"><h3>${title}</h3><svg viewBox="0 0 ${width} ${height}" role="img" aria-label="${title}">${grid}<polygon class="chart-area" points="${area}"/><polyline class="chart-line" points="${points}"/>${dots}${labels}</svg></article>`;
};
if (data.employees) {
host.innerHTML = render('Динамика численности', data.employees, '#BE7AB9', data.unit || 'чел.');
return;
}
const unit = data.unit || 'тыс. руб.';
host.innerHTML = render(`Выручка, ${unit}`, data.income, '#73b8e5', unit) + render(`Чистая прибыль, ${unit}`, data.profit, '#55bd79', unit);
});
document.addEventListener('click', event => {
const trigger = event.target.closest('.detail-button');
if (trigger) {
const template = document.querySelector(`#${CSS.escape(trigger.dataset.modalSource)}`);
if (!template) return;
viewport.replaceChildren(template.content.cloneNode(true));
renderCharts(viewport);
modal.showModal();
return;
}
if (event.target.closest('.modal-close')) modal.close();
if (event.target === modal) modal.close();
});
document.addEventListener('keydown', event => { if (event.key === 'Escape' && modal?.open) modal.close(); });
renderCharts(document);
})();