update code of dash and report of cont_client and devlp abstract of qty

This commit is contained in:
2026-07-30 14:38:37 +05:30
parent 12b2032430
commit bf1df3a817
42 changed files with 3066 additions and 952 deletions

View File

@@ -1,117 +1,312 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css">
<div class="container mt-3">
<script src="https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js"></script>
<h4>RA Bill Dashboard</h4>
<div class="row mb-3">
<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>
<!-- Contractor -->
<div class="col-md-4">
<select id="subcontractor" class="form-control">
<option value="">Select Contractor</option>
{% for s in subcontractors %}
<option value="{{s.id}}">{{s.subcontractor_name}}</option>
{% endfor %}
</select>
</div>
<!-- Category -->
<div class="col-md-4">
<select id="category" class="form-control">
<option value="">Select Category</option>
<option value="trench_excavation">Trench Excavation</option>
</select>
</div>
<!-- RA Bill -->
<div class="col-md-4">
<select id="ra_bill" class="form-control">
<option value="">RA Bill</option>
</select>
</div>
</div>
<div class="card">
<div class="card-body">
<canvas id="comparisonChart"></canvas>
<!-- 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="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>
<button class="btn btn-primary" id="searchBtn">
<i class="bi bi-search"></i>Search
</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">
<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>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<!-- BAR -->
<div style="height:600px">
<canvas id="barChart"></canvas>
</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 chart;
let barChart;
let pieChart;
let raBillChoice;
// ✅ Load RA Bills
function loadRABills() {
/* Load RA Bills */
function loadRABills(){
let subcontractor = document.getElementById("subcontractor").value
let category = document.getElementById("category").value
if (!subcontractor || !category) return
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 => {
.then(res => res.json())
.then(data => {
let ra = document.getElementById("ra_bill")
ra.innerHTML = '<option value="">RA Bill</option>'
raBillChoice.clearStore();
let choices = [];
data.ra_bills.forEach(function(bill){
choices.push({
value: bill,
label: bill
});
});
raBillChoice.setChoices(
choices,
"value",
"label",
true
);
});
data.ra_bills.forEach(bill => {
ra.innerHTML += `<option value="${bill}">${bill}</option>`
})
})
}
// ✅ Load Chart
function loadChart() {
/* Search */
function loadDashboard() {
let subcontractor = document.getElementById("subcontractor").value
let ra_bill = document.getElementById("ra_bill").value
const subcontractor = document.getElementById("subcontractor").value;
const category = document.getElementById("category").value;
fetch(`/dashboard/api/trench-analysis?subcontractor=${subcontractor}&ra_bill=${ra_bill}`)
.then(res => res.json())
let raBills = [];
if (raBillChoice) {
raBills = raBillChoice.getValue(true);
}
fetch(`/dashboard/api/trench-analysis?subcontractor=${subcontractor}&category=${category}&ra_bill=${raBills.join(",")}`)
.then(response => response.json())
.then(data => {
if (chart) chart.destroy()
console.log(data);
chart = new Chart(document.getElementById("comparisonChart"), {
type: "bar",
data: {
labels: data.labels,
datasets: [
{
label: "Depth",
data: data.depth,
backgroundColor: "green"
},
{
label: "Excavation Qty (cum)",
data: data.qty,
backgroundColor: "blue"
}
]
drawBar(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: "Excavation Comparison"
},
legend: {
position: "bottom"
}
},
scales: {
x: {
ticks: {
autoSkip: false,
maxRotation: 45,
minRotation: 45
}
},
y: {
beginAtZero: true,
title: {
display: true,
text: "Excavation Qty (Cum)"
}
}
}
}
});
}
// Events
document.getElementById("subcontractor").addEventListener("change", () => {
loadRABills()
})
/* EVENTS */
document.getElementById("subcontractor").addEventListener("change", loadRABills);
document.getElementById("category").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: ""
});
});
document.getElementById("ra_bill").addEventListener("change", loadChart)
</script>