379 lines
11 KiB
HTML
379 lines
11 KiB
HTML
{% extends "base.html" %}
|
|
{% block content %}
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css">
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js"></script>
|
|
|
|
|
|
<div class="container-fluid py-4">
|
|
|
|
<!-- HEADER -->
|
|
<div class="card shadow border-0 mb-4">
|
|
<div class="card-body">
|
|
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
|
|
<div>
|
|
<h3 class="fw-bold text-primary">
|
|
<i class="bi bi-bar-chart-fill"></i>
|
|
RA Bill Analytics Dashboard
|
|
</h3>
|
|
|
|
<small class="text-muted">
|
|
Compare Quantity, Depth & RA Bill Analytics
|
|
</small>
|
|
</div>
|
|
|
|
<div>
|
|
<button class="btn btn-success" id="exportExcel">
|
|
<i class="bi bi-file-earmark-excel"></i>
|
|
Excel
|
|
</button>
|
|
|
|
<button class="btn btn-danger" id="exportPDF">
|
|
<i class="bi bi-file-earmark-pdf"></i>
|
|
PDF
|
|
</button>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FILTERS -->
|
|
<div class="card shadow-sm mb-4">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-funnel-fill"></i>
|
|
Filters
|
|
</h5>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row g-3">
|
|
|
|
<!-- Contractor -->
|
|
<div class="col-lg-4">
|
|
<label class="form-label fw-bold"> Subcontractor </label>
|
|
<select class="form-select" id="subcontractor">
|
|
<option value="">--- select contractor ---</option>
|
|
{% for s in subcontractors %}
|
|
<option value="{{s.id}}">
|
|
{{s.subcontractor_name}}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Category -->
|
|
<div class="col-lg-4">
|
|
<label class="form-label fw-bold">Category</label>
|
|
<select class="form-select" id="category">
|
|
<option value="">--- select category ---</option>
|
|
<option value="trench_excavation">Trench Excavation</option>
|
|
<option value="manhole_excavation">Manhole Excavation</option>
|
|
<option value="Manhole_Domestic_Chamber">Manhole Domestic Chamber</option>
|
|
<option value="Laying">Pipe Laying</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- RA Bill -->
|
|
<div class="col-lg-4">
|
|
<label class="form-label fw-bold"> RA Bills</label>
|
|
<select id="ra_bill" class="form-select" multiple></select>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<hr>
|
|
<!-- Search button -->
|
|
<button class="btn btn-primary" id="searchBtn">
|
|
<i class="bi bi-search"></i>Search
|
|
</button>
|
|
<!-- Reset button -->
|
|
<button class="btn btn-secondary" id="resetBtn">
|
|
<i class="bi bi-arrow-clockwise"></i>Reset
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- TABS -->
|
|
<div class="card shadow">
|
|
|
|
<div class="card-header">
|
|
<ul class="nav nav-pills">
|
|
<!--Bar Chart Tab -->
|
|
<li class="nav-item">
|
|
<button class="nav-link active"
|
|
data-bs-toggle="tab"
|
|
data-bs-target="#barTab">
|
|
<i class="bi bi-bar-chart"></i> Bar Chart
|
|
</button>
|
|
</li>
|
|
|
|
<!-- Data Table Tab -->
|
|
<li class="nav-item">
|
|
<button class="nav-link"
|
|
data-bs-toggle="tab"
|
|
data-bs-target="#tableTab">
|
|
<i class="bi bi-table"></i> Data Table
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<div class="tab-content">
|
|
<!-- BAR TAB -->
|
|
<div class="tab-pane fade show active" id="barTab">
|
|
<div style="height:600px">
|
|
<canvas id="barChart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- TABLE TAB -->
|
|
<div class="tab-pane fade" id="tableTab">
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-hover" id="resultTable">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>Sr No</th>
|
|
<th>Strata Type & Depth</th>
|
|
<th class="text-end">Client Qty</th>
|
|
<th class="text-end">Sub Contractor Qty</th>
|
|
<th class="text-end">Difference</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
|
|
<script>
|
|
|
|
let barChart;
|
|
let raBillChoice;
|
|
|
|
/* Load RA Bills */
|
|
function loadRABills(){
|
|
|
|
let subcontractor = document.getElementById("subcontractor").value
|
|
let category = document.getElementById("category").value
|
|
|
|
if (!raBillChoice)
|
|
return;
|
|
|
|
if (!subcontractor || !category) {
|
|
|
|
raBillChoice.clearStore();
|
|
|
|
return;
|
|
}
|
|
|
|
fetch(`/dashboard/api/get-ra-bills?subcontractor=${subcontractor}&category=${category}`)
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
|
|
raBillChoice.clearStore();
|
|
|
|
let choices = [];
|
|
|
|
data.ra_bills.forEach(function(bill){
|
|
|
|
choices.push({
|
|
|
|
value: bill,
|
|
|
|
label: bill
|
|
|
|
});
|
|
|
|
});
|
|
|
|
raBillChoice.setChoices(
|
|
choices,
|
|
"value",
|
|
"label",
|
|
true
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
/* Search */
|
|
function loadDashboard() {
|
|
const subcontractor = document.getElementById("subcontractor").value;
|
|
const category = document.getElementById("category").value;
|
|
|
|
let raBills = [];
|
|
|
|
if (raBillChoice) {
|
|
raBills = raBillChoice.getValue(true);
|
|
}
|
|
|
|
let apiUrl = "";
|
|
|
|
switch (category) {
|
|
|
|
case "trench_excavation":
|
|
apiUrl = "/dashboard/api/tr-analysis";
|
|
break;
|
|
|
|
case "manhole_excavation":
|
|
apiUrl = "/dashboard/api/mh-analysis";
|
|
break;
|
|
|
|
case "Manhole_Domestic_Chamber":
|
|
apiUrl = "/dashboard/api/mdc-analysis";
|
|
break;
|
|
|
|
case "Laying":
|
|
apiUrl = "/dashboard/api/laying-analysis";
|
|
break;
|
|
|
|
default:
|
|
alert("Please select category");
|
|
return;
|
|
}
|
|
|
|
fetch(`${apiUrl}?subcontractor=${subcontractor}&category=${category}&ra_bill=${raBills.join(",")}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
drawBar(data);
|
|
drawTable(data);
|
|
})
|
|
.catch(err => console.error(err));
|
|
|
|
}
|
|
|
|
/* BAR */
|
|
function drawBar(data) {
|
|
if (barChart) {
|
|
barChart.destroy();
|
|
}
|
|
const ctx = document.getElementById("barChart");
|
|
barChart = new Chart(ctx, {
|
|
type: "bar",
|
|
data: {
|
|
labels: data.labels,
|
|
datasets: [
|
|
{
|
|
label: "Client Qty",
|
|
data: data.client_qty,
|
|
backgroundColor: "#0d6efd",
|
|
borderColor: "#0d6efd",
|
|
borderWidth: 1
|
|
},
|
|
{
|
|
label: "Sub-Contractor Qty",
|
|
data: data.sub_qty,
|
|
backgroundColor: "#fd7e14",
|
|
borderColor: "#fd7e14",
|
|
borderWidth: 1
|
|
}
|
|
]
|
|
},
|
|
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
interaction: {
|
|
mode: "index",
|
|
intersect: false
|
|
},
|
|
|
|
plugins: {
|
|
title: {
|
|
display: true,
|
|
text: data.title
|
|
},
|
|
legend: {
|
|
position: "bottom"
|
|
}
|
|
},
|
|
|
|
scales: {
|
|
x: {
|
|
ticks: {
|
|
autoSkip: false,
|
|
maxRotation: 45,
|
|
minRotation: 45
|
|
}
|
|
},
|
|
y: {
|
|
beginAtZero: true,
|
|
title: {
|
|
display: true,
|
|
text: data.y_title
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
/* TABLE */
|
|
function drawTable(data){
|
|
|
|
let html='';
|
|
for(let i=0;i<data.labels.length;i++){
|
|
const clientQty = Number(data.client_qty[i] || 0);
|
|
const subQty = Number(data.sub_qty[i] || 0);
|
|
const diff = clientQty - subQty;
|
|
|
|
html+=`
|
|
<tr>
|
|
<td class="text-center">${i + 1}</td>
|
|
<td>${data.labels[i]}</td>
|
|
<td class="text-end">${data.client_qty[i]}</td>
|
|
<td class="text-end">${data.sub_qty[i]}</td>
|
|
<td class="text-end fw-bold ${diff >= 0 ? 'text-success' : 'text-danger'}">${diff.toFixed(2)}</td>
|
|
</tr>
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
document.querySelector("#resultTable tbody").innerHTML = html;
|
|
|
|
}
|
|
|
|
/* EVENTS */
|
|
document.getElementById("subcontractor").addEventListener("change", loadRABills);
|
|
|
|
document.getElementById("category").addEventListener("change", loadRABills);
|
|
|
|
document.getElementById("searchBtn").addEventListener("click", loadDashboard);
|
|
|
|
document.getElementById("resetBtn").addEventListener("click", function () {location.reload();});
|
|
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
raBillChoice = new Choices("#ra_bill", {
|
|
removeItemButton: true,
|
|
searchEnabled: true,
|
|
searchPlaceholderValue: "Search RA Bills",
|
|
placeholder: true,
|
|
placeholderValue: "Select RA Bills",
|
|
shouldSort: false,
|
|
itemSelectText: ""
|
|
});
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
{% endblock %} |