551 lines
21 KiB
PHP
551 lines
21 KiB
PHP
<script>
|
|
(function () {
|
|
const MIS_DATA = <?= json_encode($vm ?? [], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>;
|
|
const embedMode = <?= !empty($embed) ? 'true' : 'false' ?>;
|
|
|
|
const COLORS = {
|
|
blue: '#2E86DE',
|
|
navy: '#1B3F8C',
|
|
orange: '#E8862C',
|
|
purple: '#6A3D9A',
|
|
red: '#C8102E',
|
|
female: '#1A3399',
|
|
male: '#6A3D9A'
|
|
};
|
|
|
|
function fmt(n) {
|
|
if (n === '' || n === null || n === undefined) return '';
|
|
return Number(n).toLocaleString('en-IN');
|
|
}
|
|
function dash(v) { return (v === 0 || v === '0') ? '—' : v; }
|
|
function el(id) { return document.getElementById(id); }
|
|
function setHtml(id, html) { const node = el(id); if (node) node.innerHTML = html; }
|
|
function setText(id, text) { const node = el(id); if (node) node.textContent = text; }
|
|
|
|
const claimStatus = MIS_DATA.claimStatus || [];
|
|
setHtml('tblClaimStatus', claimStatus.map(r =>
|
|
`<tr><td>${r.status}</td><td class="num">${r.number}</td><td class="num">${fmt(r.reported)}</td><td class="num">${fmt(r.incurred)}</td></tr>`
|
|
).join(''));
|
|
|
|
const policyPremium = MIS_DATA.policyPremium || [];
|
|
setHtml('tblPolicyPremium', policyPremium.map(r =>
|
|
`<tr><td>${r.sr}</td><td>${r.label}</td><td class="num">${fmt(r.amount)}</td></tr>`
|
|
).join('') +
|
|
`<tr style="font-weight:700;background:#F0F0F3;border-top:2px solid var(--red)"><td colspan="2">Total</td><td class="num">${fmt(MIS_DATA.policyPremiumTotal || 0)}</td></tr>`);
|
|
|
|
const reimbTAT = MIS_DATA.reimbTAT || [];
|
|
setHtml('tblReimbTAT', reimbTAT.map(r =>
|
|
`<tr><td>${r.range}</td><td class="num">${r.count}</td><td class="num">${r.pct}</td></tr>`
|
|
).join('') +
|
|
`<tr style="font-weight:700;background:#F0F0F3;border-top:2px solid var(--red)"><td>Total</td><td class="num">${MIS_DATA.reimbTATTotal?.count || 0}</td><td class="num">${MIS_DATA.reimbTATTotal?.pct || 0}</td></tr>`);
|
|
|
|
const gender = MIS_DATA.gender || [];
|
|
const genderOrder = ['Male', 'Female'];
|
|
setHtml('tblGender', genderOrder.map(label => {
|
|
const row = gender.find(g => g.label === label) || { label, count: 0, amount: 0 };
|
|
return `<tr><td>${row.label}</td><td class="num">${row.count}</td><td class="num">${fmt(row.amount)}</td></tr>`;
|
|
}).join(''));
|
|
setText('tblGenderCountTotal', MIS_DATA.genderTotal?.count || 0);
|
|
setText('tblGenderAmtTotal', fmt(MIS_DATA.genderTotal?.incurred_amount || 0));
|
|
|
|
const claimType = MIS_DATA.claimType || [];
|
|
setHtml('tblClaimType', claimType.map(r =>
|
|
`<tr ${r.header ? 'class="subhead"' : ''}><td>${r.header ? '' : ' '}${r.type}</td><td class="num">${r.count}</td><td class="num">${r.countPct}</td><td class="num">${fmt(r.amount)}</td><td class="num">${r.amtPct}</td><td class="num">${fmt(r.incurred)}</td><td class="num">${r.incPct}</td></tr>`
|
|
).join(''));
|
|
const ct = MIS_DATA.claimTypeTotal || {};
|
|
setText('tblClaimTypeCount', ct.count || 0);
|
|
setText('tblClaimTypeAmt', fmt(ct.amount || 0));
|
|
setText('tblClaimTypeInc', fmt(ct.incurred || 0));
|
|
|
|
const relation = MIS_DATA.relation || [];
|
|
setHtml('tblRelation', relation.map(r =>
|
|
`<tr><td>${r.label}</td><td class="num">${r.count}</td><td class="num">${r.cpct}</td><td class="num">${fmt(r.amt)}</td><td class="num">${r.apct}</td></tr>`
|
|
).join(''));
|
|
setText('tblRelationCount', MIS_DATA.relationTotal?.count || 0);
|
|
setText('tblRelationAmt', fmt(MIS_DATA.relationTotal?.incurred_amount || 0));
|
|
|
|
const memberType = MIS_DATA.memberType || [];
|
|
setHtml('tblMemberType', memberType.map(r =>
|
|
`<tr><td>${r.label}</td><td class="num">${r.count}</td><td class="num">${r.cpct}</td><td class="num">${fmt(r.amt)}</td><td class="num">${r.apct}</td></tr>`
|
|
).join(''));
|
|
setText('tblMemberCount', MIS_DATA.memberTypeTotal?.count || 0);
|
|
setText('tblMemberAmt', fmt(MIS_DATA.memberTypeTotal?.incurred_amount || 0));
|
|
|
|
const age = MIS_DATA.age || [];
|
|
setHtml('tblAge', age.map(r =>
|
|
`<tr><td>${r.band}</td><td class="num">${r.count}</td><td class="num">${r.cpct}</td><td class="num">${fmt(r.amt)}</td><td class="num">${r.apct}</td></tr>`
|
|
).join(''));
|
|
setText('tblAgeCount', MIS_DATA.ageTotal?.count || 0);
|
|
setText('tblAgeAmt', fmt(MIS_DATA.ageTotal?.incurred_amount || 0));
|
|
|
|
const diagnosis = MIS_DATA.diagnosis || [];
|
|
setHtml('tblDiagnosis', diagnosis.map(r =>
|
|
`<tr><td>${r.name}</td><td class="num">${r.count}</td><td class="num">${r.cpct}</td><td class="num">${fmt(r.amt)}</td><td class="num">${r.apct}</td><td class="num">${r.acs ? fmt(r.acs) : ''}</td><td class="num">${r.lr}</td></tr>`
|
|
).join(''));
|
|
const dt = MIS_DATA.diagnosisTotal || {};
|
|
setText('tblDiagCount', dt.count || 0);
|
|
setText('tblDiagAmt', fmt(dt.amt || 0));
|
|
setText('tblDiagAcs', fmt(dt.acs || 0));
|
|
setText('tblDiagLr', dt.lr || 0);
|
|
|
|
function renderUtil(id, data, prefix) {
|
|
const rows = data?.rows || [];
|
|
setHtml(id, rows.map(r =>
|
|
`<tr><td>${r.claims}</td><td class="num">${r.beneficiaries}</td><td class="num">${r.incurredCount}</td><td class="num">${r.countPct || dash(0)}</td><td class="num">${fmt(r.amount)}</td><td class="num">${r.amountPct || dash(0)}</td></tr>`
|
|
).join(''));
|
|
const t = data?.total || {};
|
|
setText(prefix + 'Ben', t.beneficiaries || 0);
|
|
setText(prefix + 'Cnt', t.incurredCount || 0);
|
|
setText(prefix + 'Amt', fmt(t.amount || 0));
|
|
}
|
|
renderUtil('tblUtilEmp', MIS_DATA.utilizationEmployees, 'tblUtilEmp');
|
|
renderUtil('tblUtilDep', MIS_DATA.utilizationDependents, 'tblUtilDep');
|
|
|
|
const hospitals = MIS_DATA.hospitals || [];
|
|
setHtml('tblHospital', hospitals.map(r =>
|
|
`<tr><td>${r.name}</td><td class="num">${r.count}</td><td class="num">${r.cpct}</td><td class="num">${fmt(r.amt)}</td><td class="num">${r.apct}</td></tr>`
|
|
).join(''));
|
|
const ht = MIS_DATA.hospitalTotal || {};
|
|
setText('tblHospitalCount', ht.count || 0);
|
|
setText('tblHospitalAmt', fmt(ht.incurred_amount || 0));
|
|
|
|
const cities = MIS_DATA.cities || [];
|
|
setHtml('tblCity', cities.map(r =>
|
|
`<tr><td>${r.city}</td><td class="num">${r.count}</td><td class="num">${fmt(r.amt)}</td><td class="num">${r.paidCount}</td><td class="num">${r.paidAmt !== '' && r.paidAmt !== null ? Number(r.paidAmt).toFixed(2) : ''}</td><td class="num">${r.outCount}</td><td class="num">${r.outAmt !== '' && r.outAmt !== null ? fmt(r.outAmt) : ''}</td><td class="num">${r.acs !== '' && r.acs !== null ? fmt(r.acs) : ''}</td></tr>`
|
|
).join(''));
|
|
const ct2 = MIS_DATA.cityTotals || {};
|
|
setText('tblCityCount', ct2.count || 0);
|
|
setText('tblCityAmt', fmt(ct2.amt || 0));
|
|
setText('tblCityPaidCnt', ct2.paidCount || 0);
|
|
setText('tblCityPaidAmt', Number(ct2.paidAmt || 0).toFixed(2));
|
|
setText('tblCityOutCnt', ct2.outCount || 0);
|
|
setText('tblCityOutAmt', fmt(ct2.outAmt || 0));
|
|
setText('tblCityAcs', fmt(ct2.acs || 0));
|
|
|
|
if (embedMode || typeof Chart === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
Chart.defaults.font.family = 'Segoe UI, Arial, sans-serif';
|
|
Chart.defaults.font.size = 11;
|
|
Chart.defaults.color = '#333';
|
|
|
|
const statusColors = [COLORS.blue, COLORS.navy, COLORS.orange, COLORS.purple];
|
|
const statusLabels = ['Reported', 'Settled', 'Outstanding', 'Rejected'];
|
|
const amountData = claimStatus.map(r => r.reported || 0);
|
|
const countData = claimStatus.map(r => r.number || 0);
|
|
|
|
/* Nested donut: outer = Claim Amount, inner = Claim Count */
|
|
const donutLeaderPlugin = {
|
|
id: 'donutLeaderPlugin',
|
|
afterDatasetsDraw(chart) {
|
|
const { ctx } = chart;
|
|
const outerMeta = chart.getDatasetMeta(0);
|
|
const innerMeta = chart.getDatasetMeta(1);
|
|
if (!outerMeta || !innerMeta) return;
|
|
|
|
outerMeta.data.forEach((arc, i) => {
|
|
const val = amountData[i];
|
|
if (!val) return;
|
|
const pos = arc.tooltipPosition();
|
|
const angle = (arc.startAngle + arc.endAngle) / 2;
|
|
const r = arc.outerRadius + 18;
|
|
const x = arc.x + Math.cos(angle) * r;
|
|
const y = arc.y + Math.sin(angle) * r;
|
|
const lx = arc.x + Math.cos(angle) * (arc.outerRadius + 4);
|
|
const ly = arc.y + Math.sin(angle) * (arc.outerRadius + 4);
|
|
ctx.save();
|
|
ctx.strokeStyle = '#999';
|
|
ctx.lineWidth = 0.8;
|
|
ctx.beginPath();
|
|
ctx.moveTo(lx, ly);
|
|
ctx.lineTo(x, y);
|
|
ctx.stroke();
|
|
ctx.font = 'bold 11px Segoe UI, Arial';
|
|
ctx.fillStyle = '#222';
|
|
ctx.textAlign = x < arc.x ? 'right' : 'left';
|
|
ctx.fillText(fmt(val), x + (x < arc.x ? -4 : 4), y + 4);
|
|
ctx.restore();
|
|
});
|
|
|
|
innerMeta.data.forEach((arc, i) => {
|
|
const val = countData[i];
|
|
if (!val) return;
|
|
const pos = arc.tooltipPosition();
|
|
ctx.save();
|
|
ctx.font = 'bold 12px Segoe UI, Arial';
|
|
ctx.fillStyle = '#fff';
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'middle';
|
|
ctx.fillText(String(val), pos.x, pos.y);
|
|
ctx.restore();
|
|
});
|
|
}
|
|
};
|
|
|
|
new Chart(el('chartDonut1'), {
|
|
type: 'doughnut',
|
|
data: {
|
|
labels: statusLabels,
|
|
datasets: [
|
|
{
|
|
label: 'Claim Amount',
|
|
data: amountData,
|
|
backgroundColor: statusColors,
|
|
borderWidth: 2,
|
|
borderColor: '#fff',
|
|
weight: 1.1
|
|
},
|
|
{
|
|
label: 'Claim Count',
|
|
data: countData,
|
|
backgroundColor: statusColors,
|
|
borderWidth: 2,
|
|
borderColor: '#fff',
|
|
weight: 0.55
|
|
}
|
|
]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
cutout: '42%',
|
|
plugins: {
|
|
legend: { display: false },
|
|
tooltip: {
|
|
callbacks: {
|
|
label: (c) => c.dataset.label + ': ' + (c.datasetIndex === 1 ? c.raw : fmt(c.raw))
|
|
}
|
|
}
|
|
}
|
|
},
|
|
plugins: [donutLeaderPlugin]
|
|
});
|
|
|
|
/* Pre-Auth TAT — column chart with % labels above bars */
|
|
const preAuth = MIS_DATA.preAuthTAT || { within: 100, above: 0 };
|
|
const preAuthValues = [preAuth.within, preAuth.above];
|
|
|
|
function maxInDatasets(datasets) {
|
|
let max = 0;
|
|
(datasets || []).forEach(ds => {
|
|
(ds.data || []).forEach(v => { max = Math.max(max, Number(v) || 0); });
|
|
});
|
|
return max;
|
|
}
|
|
|
|
const barTopLabelsPlugin = {
|
|
id: 'barTopLabels',
|
|
afterDatasetsDraw(chart) {
|
|
const cfg = chart.options.plugins?.barTopLabels || {};
|
|
if (cfg.enabled === false || chart.options.indexAxis === 'y') return;
|
|
|
|
const formatType = cfg.format || 'number';
|
|
const formatters = {
|
|
percent: v => Number(v).toFixed(2) + '%',
|
|
count: v => String(Math.round(Number(v))),
|
|
amount: v => fmt(v),
|
|
number: v => fmt(v)
|
|
};
|
|
const labelFn = formatters[formatType] || formatters.number;
|
|
const hideZero = cfg.hideZero !== false;
|
|
const { ctx } = chart;
|
|
const dsCount = chart.data.datasets.length;
|
|
|
|
chart.data.datasets.forEach((ds, di) => {
|
|
chart.getDatasetMeta(di).data.forEach((bar, i) => {
|
|
const val = Number(ds.data[i]);
|
|
if (hideZero && (!val || val === 0)) return;
|
|
const pos = bar.tooltipPosition();
|
|
const offsetX = dsCount > 1 ? (di - (dsCount - 1) / 2) * 14 : 0;
|
|
ctx.save();
|
|
ctx.font = 'bold 10px Segoe UI, Arial';
|
|
ctx.fillStyle = '#222';
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'bottom';
|
|
ctx.fillText(labelFn(val), pos.x + offsetX, pos.y - 5);
|
|
ctx.restore();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
const chartLayout = { padding: { top: 28, left: 4, right: 4 } };
|
|
|
|
const hBarValuePlugin = {
|
|
id: 'hBarValuePlugin',
|
|
afterDatasetsDraw(chart) {
|
|
const cfg = chart.options.plugins?.hBarLabels || {};
|
|
if (cfg.enabled === false || chart.options.indexAxis !== 'y') return;
|
|
|
|
const formatType = cfg.format || 'amount';
|
|
const formatters = {
|
|
count: v => String(Math.round(Number(v))),
|
|
amount: v => fmt(v)
|
|
};
|
|
const labelFn = formatters[formatType] || formatters.amount;
|
|
|
|
const { ctx } = chart;
|
|
chart.getDatasetMeta(0).data.forEach((bar, i) => {
|
|
const val = chart.data.datasets[0].data[i];
|
|
if (!val && val !== 0) return;
|
|
const props = bar.getProps(['x', 'y', 'base', 'width'], true);
|
|
const barLeft = Math.min(props.x, props.base);
|
|
const barRight = Math.max(props.x, props.base);
|
|
const barW = Math.abs(barRight - barLeft);
|
|
const midX = barLeft + barW / 2;
|
|
const text = labelFn(val);
|
|
ctx.save();
|
|
ctx.font = 'bold 11px Segoe UI, Arial';
|
|
const tw = ctx.measureText(text).width + 14;
|
|
const th = 20;
|
|
const rx = midX - tw / 2;
|
|
const ry = props.y - th / 2;
|
|
ctx.fillStyle = 'rgba(255,255,255,0.92)';
|
|
ctx.strokeStyle = '#d1d5db';
|
|
ctx.lineWidth = 0.5;
|
|
ctx.fillRect(rx, ry, tw, th);
|
|
ctx.strokeRect(rx, ry, tw, th);
|
|
ctx.fillStyle = '#222';
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'middle';
|
|
ctx.fillText(text, midX, props.y);
|
|
ctx.restore();
|
|
});
|
|
}
|
|
};
|
|
|
|
Chart.register(barTopLabelsPlugin, hBarValuePlugin);
|
|
|
|
new Chart(el('chartPreAuth'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['With in 2 Hours %', 'Above 2 Hours %'],
|
|
datasets: [{ data: preAuthValues, backgroundColor: [COLORS.blue, COLORS.navy], barPercentage: 0.45, categoryPercentage: 0.7 }]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: chartLayout,
|
|
plugins: { legend: { display: false }, barTopLabels: { format: 'percent', hideZero: false } },
|
|
scales: {
|
|
x: { grid: { display: false }, border: { display: false } },
|
|
y: { display: false, suggestedMax: 115 }
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Premium / Earn Premium / Claim Incurred — horizontal bars with value pills */
|
|
const premiumBars = MIS_DATA.premiumBars || [0, 0, 0];
|
|
const premiumLabels = ['Premium', 'Earn Premium', 'Claim Incurred Amount'];
|
|
|
|
new Chart(el('chartPremiumBars'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels: premiumLabels,
|
|
datasets: [{ data: premiumBars, backgroundColor: [COLORS.navy, COLORS.blue, COLORS.orange], barThickness: 28 }]
|
|
},
|
|
options: {
|
|
indexAxis: 'y',
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: { padding: { top: 8, right: 16, bottom: 8, left: 8 } },
|
|
plugins: { legend: { display: false }, barTopLabels: { enabled: false }, hBarLabels: { format: 'amount' } },
|
|
scales: {
|
|
x: { display: false, grid: { display: false }, suggestedMax: Math.max(...premiumBars, 1) * 1.15 },
|
|
y: { grid: { display: false }, border: { display: false }, ticks: { font: { weight: 'bold', size: 12 } } }
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Gender — horizontal bar charts (Male purple, Female navy) */
|
|
const genderSorted = genderOrder.map(label => {
|
|
const found = gender.find(g => g.label === label);
|
|
return found || { label, count: 0, amount: 0 };
|
|
});
|
|
|
|
function genderBar(canvasId, valueKey) {
|
|
const labels = genderSorted.map(g => g.label);
|
|
const values = genderSorted.map(g => g[valueKey] || 0);
|
|
const colors = labels.map(l => l.toLowerCase() === 'female' ? COLORS.female : COLORS.male);
|
|
const maxVal = Math.max(...values, 1);
|
|
|
|
new Chart(el(canvasId), {
|
|
type: 'bar',
|
|
data: { labels, datasets: [{ data: values, backgroundColor: colors, barThickness: 32 }] },
|
|
options: {
|
|
indexAxis: 'y',
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: { padding: { top: 10, right: 20, bottom: 10, left: 4 } },
|
|
plugins: {
|
|
legend: { display: false },
|
|
barTopLabels: { enabled: false },
|
|
hBarLabels: { format: valueKey === 'count' ? 'count' : 'amount' }
|
|
},
|
|
scales: {
|
|
x: { display: false, grid: { display: false }, suggestedMax: maxVal * 1.2 },
|
|
y: { grid: { display: false }, border: { display: false }, ticks: { font: { weight: 'bold', size: 12 } } }
|
|
}
|
|
}
|
|
});
|
|
}
|
|
genderBar('chartGenderCount', 'count');
|
|
genderBar('chartGenderAmt', 'amount');
|
|
|
|
const pc = MIS_DATA.paidCharts || {};
|
|
const cbt = pc.countByType || {};
|
|
const paidCountData = pc.paidCount || [0, 0];
|
|
const paidAmtData = pc.paidAmt || [0, 0];
|
|
const acsData = pc.acs || [0, 0];
|
|
const amtStatusData = pc.amtByStatus || [0, 0, 0];
|
|
const countStatusCashless = [cbt.Settled?.Cashless || 0, cbt.Outstanding?.Cashless || 0, cbt.Rejected?.Cashless || 0];
|
|
const countStatusReimb = [cbt.Settled?.Reimbursement || 0, cbt.Outstanding?.Reimbursement || 0, cbt.Rejected?.Reimbursement || 0];
|
|
|
|
/* Claim Paid Count By Claim Type */
|
|
new Chart(el('chartPaidCount'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['Cashless', 'Reimbursement'],
|
|
datasets: [{ data: paidCountData, backgroundColor: [COLORS.blue, COLORS.navy], barPercentage: 0.5 }]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: chartLayout,
|
|
plugins: { legend: { display: false }, barTopLabels: { format: 'count' } },
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
ticks: { stepSize: 1, precision: 0 },
|
|
suggestedMax: Math.max(1, maxInDatasets([{ data: paidCountData }]) * 1.25)
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Claim Paid Amount and ACS */
|
|
const paidAmtDatasets = [
|
|
{ label: 'Claim Paid Amount', data: paidAmtData, backgroundColor: COLORS.blue },
|
|
{ label: 'ACS', data: acsData, backgroundColor: COLORS.orange }
|
|
];
|
|
new Chart(el('chartPaidAmtACS'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['Cashless', 'Reimbursement'],
|
|
datasets: paidAmtDatasets
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: chartLayout,
|
|
plugins: { legend: { position: 'bottom', labels: { boxWidth: 10, font: { size: 10 } } }, barTopLabels: { format: 'amount' } },
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
ticks: { callback: v => fmt(v) },
|
|
suggestedMax: maxInDatasets(paidAmtDatasets) * 1.2 || undefined
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Claim Count By Claim Status */
|
|
const countStatusDatasets = [
|
|
{ label: 'Cashless', data: countStatusCashless, backgroundColor: COLORS.blue },
|
|
{ label: 'Reimbursement', data: countStatusReimb, backgroundColor: COLORS.navy }
|
|
];
|
|
new Chart(el('chartCountStatus'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['Settled', 'Outstanding', 'Rejected'],
|
|
datasets: countStatusDatasets
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: chartLayout,
|
|
plugins: { legend: { position: 'bottom', labels: { boxWidth: 10, font: { size: 10 } } }, barTopLabels: { format: 'count' } },
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
ticks: { stepSize: 1, precision: 0 },
|
|
suggestedMax: Math.max(1, maxInDatasets(countStatusDatasets) * 1.25)
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Claim Amount By Claim Status */
|
|
new Chart(el('chartAmtStatus'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['Settled', 'Outstanding', 'Rejected'],
|
|
datasets: [{ data: amtStatusData, backgroundColor: [COLORS.blue, COLORS.orange, COLORS.purple], barPercentage: 0.55 }]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: chartLayout,
|
|
plugins: { legend: { display: false }, barTopLabels: { format: 'amount' } },
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
ticks: { callback: v => fmt(v) },
|
|
suggestedMax: maxInDatasets([{ data: amtStatusData }]) * 1.2 || undefined
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Monthly registration charts */
|
|
const months = MIS_DATA.months || [];
|
|
const paidCountMonth = MIS_DATA.paidCountByMonth || [];
|
|
const outCountMonth = MIS_DATA.outCountByMonth || [];
|
|
const paidAmtMonth = MIS_DATA.paidAmtByMonth || [];
|
|
const outAmtMonth = MIS_DATA.outAmtByMonth || [];
|
|
|
|
const monthCountDatasets = [
|
|
{ label: 'Claim Paid Count', data: paidCountMonth, backgroundColor: COLORS.blue, order: 2, barPercentage: 0.7, categoryPercentage: 0.8 },
|
|
{ label: 'Claim Outstanding Count', data: outCountMonth, backgroundColor: 'rgba(46,134,222,0.12)', borderColor: COLORS.navy, borderWidth: 2, order: 1, barPercentage: 0.95, categoryPercentage: 0.8 }
|
|
];
|
|
const monthAmtDatasets = [
|
|
{ label: 'Claim Paid Amount', data: paidAmtMonth, backgroundColor: COLORS.blue, order: 2, barPercentage: 0.7, categoryPercentage: 0.8 },
|
|
{ label: 'Claim Outstanding Amount', data: outAmtMonth, backgroundColor: 'rgba(46,134,222,0.12)', borderColor: COLORS.navy, borderWidth: 2, order: 1, barPercentage: 0.95, categoryPercentage: 0.8 }
|
|
];
|
|
|
|
const monthCountMax = maxInDatasets(monthCountDatasets);
|
|
const monthAmtMax = maxInDatasets(monthAmtDatasets);
|
|
|
|
new Chart(el('chartMonthCount'), {
|
|
type: 'bar',
|
|
data: { labels: months, datasets: monthCountDatasets },
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: chartLayout,
|
|
plugins: { legend: { position: 'bottom', labels: { boxWidth: 10, font: { size: 10 } } }, barTopLabels: { format: 'count' } },
|
|
scales: {
|
|
y: { position: 'right', beginAtZero: true, suggestedMax: monthCountMax * 1.2 || undefined, ticks: { precision: 0 } },
|
|
x: { grid: { display: false } }
|
|
}
|
|
}
|
|
});
|
|
|
|
new Chart(el('chartMonthAmt'), {
|
|
type: 'bar',
|
|
data: { labels: months, datasets: monthAmtDatasets },
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
layout: chartLayout,
|
|
plugins: { legend: { position: 'bottom', labels: { boxWidth: 10, font: { size: 10 } } }, barTopLabels: { format: 'amount' } },
|
|
scales: {
|
|
y: { position: 'right', beginAtZero: true, suggestedMax: monthAmtMax * 1.2 || undefined, ticks: { callback: v => fmt(v) } },
|
|
x: { grid: { display: false } }
|
|
}
|
|
}
|
|
});
|
|
})();
|
|
</script>
|