auto_repair_saas/templates/dashboard/index.html
{% extends "base.html" %}
{% block content %}
<div class="row mb-4">
<div class="col">
<h4>Dashboard</h4>
</div>
<div class="col">
<div class="btn-group shadow-0 float-end" role="group">
<button type="button" class="btn btn-primary" id="data-week"
onclick="fetchDashboardData('week')">
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"
id="data-week-loading" hidden></span>
Week
</button>
<button type="button" class="btn btn-primary" id="data-month"
onclick="fetchDashboardData('month')">
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"
id="data-month-loading" hidden></span>
Month
</button>
<button type="button" class="btn btn-primary" id="data-year"
onclick="fetchDashboardData('year')">
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"
id="data-year-loading" hidden></span>
Year
</button>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-body">
<p class="card-title text-muted text-uppercase">sales</p>
<div class="row">
<span class="card-text fs-3" id="total-sales"></span>
<small class="text-success">
<i id="total-sales-growth-icon"></i>
<span id="total-sales-growth"></span>
</small>
</div>
<div class="row">
<div class="col-12">
<canvas id="sales-chart" height="80"></canvas>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-6">
<div class="card">
<div class="card-body">
<p class="card-title text-muted text-uppercase">Top earners</p>
<div class="row">
<div class="col-12">
<canvas id="top-earners-chart" height="110"></canvas>
</div>
</div>
</div>
</div>
</div>
<div class="col-6">
<div class="card">
<div class="card-body">
<p class="card-title text-muted text-uppercase">jobs overview</p>
<table class="table table-sm">
<tbody>
<tr>
<th scope="row">Pending Estimates</th>
<td id="pending-estimates-count"></td>
<td id="pending-estimates-charged"></td>
</tr>
<tr>
<th scope="row">Confirmed Estimates</th>
<td id="confirmed-estimates-count"></td>
<td id="confirmed-estimates-charged"></td>
</tr>
<tr>
<th scope="row">In Progress</th>
<td id="in-progress-jobs-count"></td>
<td id="in-progress-jobs-charged"></td>
</tr>
<tr>
<th scope="row">Done</th>
<td id="done-jobs-count"></td>
<td id="done-jobs-charged"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
let salesChart, topEarnersChart
const fetchDashboardData = (period) => {
let active = document.querySelectorAll(".custom-active-blue");
[].forEach.call(active, function (el) {
el.classList.remove("custom-active-blue")
})
if (period === 'month') {
document.getElementById('data-month').classList.add('custom-active-blue')
document.getElementById('data-month').setAttribute('disabled', 'true')
document.getElementById('data-month-loading').removeAttribute('hidden')
} else if (period === 'year') {
document.getElementById('data-year').classList.add('custom-active-blue')
document.getElementById('data-year').setAttribute('disabled', 'true')
document.getElementById('data-year-loading').removeAttribute('hidden')
} else {
document.getElementById('data-week').classList.add('custom-active-blue')
document.getElementById('data-week').setAttribute('disabled', 'true')
document.getElementById('data-week-loading').removeAttribute('hidden')
}
fetch(`/dashboard/data?period=${period}`)
.then(response => response.json())
.then(data => {
document.getElementById('total-sales').textContent = `KSh. ${data.sales.toLocaleString()}`
populateSalesChart(data)
populateTopEarnersChart(data.top_earners)
document.getElementById('pending-estimates-count').textContent = `${data.pending_estimates_count} Orders`
document.getElementById('pending-estimates-charged').textContent = `KSh. ${data.pending_estimates_charged}`
document.getElementById('confirmed-estimates-count').textContent = `${data.confirmed_estimates_count} Orders`
document.getElementById('confirmed-estimates-charged').textContent = `KSh. ${data.confirmed_estimates_charged}`
document.getElementById('in-progress-jobs-count').textContent = `${data.jobs_in_progress_count} Orders`
document.getElementById('in-progress-jobs-charged').textContent = `KSh. ${data.jobs_in_progress_charged}`
document.getElementById('done-jobs-count').textContent = `${data.jobs_done_count} Orders`
document.getElementById('done-jobs-charged').textContent = `KSh. ${data.jobs_done_charged}`
clearLoaders()
})
.catch((error) => {
iziToast.error({
title: 'Error',
message: error,
maxWidth: 310
})
})
}
const populateSalesChart = salesData => {
salesChart && salesChart.destroy()
let chartOptions = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
const salesCard = document.getElementById('sales-chart')
salesChart = new Chart(salesCard, {
type: 'bar',
data: {
datasets: [
{
label: 'Sales',
data: salesData.overall_job_charges,
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
},
{
label: 'Cash',
data: salesData.cash_job_charges,
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255, 99, 132, 1)',
type: 'line',
fill: false,
},
{
label: 'Card',
data: salesData.card_job_charges,
backgroundColor: 'rgba(153, 102, 255, 0.2)',
borderColor: 'rgba(153, 102, 255, 1)',
type: 'line',
fill: false,
},
{
label: 'M-Pesa',
data: salesData.mpesa_job_charges,
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
type: 'line',
fill: false,
},
],
labels: salesData.chart_dates
},
options: chartOptions
})
}
const populateTopEarnersChart = topEarnersData => {
topEarnersChart && topEarnersChart.destroy()
let chartOptions = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
const topEarnersCard = document.getElementById('top-earners-chart')
topEarnersChart = new Chart(topEarnersCard, {
type: 'horizontalBar',
data: {
datasets: [
{
label: 'Sales',
data: topEarnersData.map(staff => staff.earnings),
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
},
],
labels: topEarnersData.map(staff => staff.name)
},
options: chartOptions
})
}
const clearLoaders = () => {
let loaders = document.getElementsByClassName('spinner-border');
[].forEach.call(loaders, function (el) {
el.setAttribute('hidden', 'true')
})
let buttons = document.getElementsByClassName('btn');
[].forEach.call(buttons, function (el) {
el.removeAttribute('disabled')
})
}
fetchDashboardData(period = 'week')
</script>
{% endblock %}