update code of dash and report of cont_client and devlp abstract of qty
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user