Changes done in client report page
This commit is contained in:
@@ -1,74 +1,347 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid mt-4">
|
||||
<h2 class="mb-4">Client RA Bills Reports</h2>
|
||||
|
||||
<div class="card p-4 shadow-sm mb-5">
|
||||
<form method="POST" class="loading-form">
|
||||
<label class="form-label fw-bold">RA Bill No</label>
|
||||
<input type="text" name="RA_Bill_No" class="form-control mb-3" value="{{ ra_val }}" required>
|
||||
<div class="container-fluid py-4">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<button type="submit" name="action" value="preview" class="btn btn-secondary w-100">Preview
|
||||
Data</button>
|
||||
<!-- Page Header -->
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h2 class="fw-bold text-primary mb-1">
|
||||
<i class="bi bi-file-earmark-bar-graph"></i>
|
||||
Client Report
|
||||
</h2>
|
||||
<small class="text-muted">
|
||||
View, Filter, Edit and Delete Client Records
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<button type="submit" name="action" value="download" class="btn btn-primary w-100">Download Excel Report</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% if tables.tr or tables.mh or tables.dc or tables.laying %}
|
||||
<div class="card shadow-sm p-4">
|
||||
<h4 class="mb-3">Table Preview</h4>
|
||||
|
||||
<ul class="nav nav-tabs" id="reportTabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link active" id="tr-tab" data-bs-toggle="tab" data-bs-target="#tr"
|
||||
type="button">Tr.Ex </button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" id="mh-tab" data-bs-toggle="tab" data-bs-target="#mh" type="button">Mh.Ex
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" id="dc-tab" data-bs-toggle="tab" data-bs-target="#dc" type="button">MH & DC
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" id="laying-tab" data-bs-toggle="tab" data-bs-target="#laying" type="button">Laying
|
||||
& Bedding </button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content mt-3" id="reportTabsContent">
|
||||
<div class="tab-pane fade show active" id="tr" role="tabpanel">
|
||||
<div class="table-responsive" style="max-height: 500px;">
|
||||
{{ tables.tr|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="mh" role="tabpanel">
|
||||
<div class="table-responsive" style="max-height: 500px;">
|
||||
{{ tables.mh|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="dc" role="tabpanel">
|
||||
<div class="table-responsive" style="max-height: 500px;">
|
||||
{{ tables.dc|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="laying" role="tabpanel">
|
||||
<div class="table-responsive" style="max-height: 500px;">
|
||||
{{ tables.laying|safe }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Filter Card -->
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-funnel-fill"></i>
|
||||
Report Filters
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" class="loading-form">
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label fw-semibold">
|
||||
RA Bill No
|
||||
<span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text" name="RA_Bill_No" class="form-control" placeholder="Enter RA Bill"
|
||||
value="{{ ra_val or '' }}" required>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label fw-semibold"> MH No </label>
|
||||
<input type="text" name="mh_no" class="form-control" placeholder="Enter MH No"
|
||||
value="{{ mh_no_val or '' }}">
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label fw-semibold"> Location </label>
|
||||
<input type="text" name="location" class="form-control" placeholder="Project Location"
|
||||
value="{{ location_val or '' }}">
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<label class="form-label fw-semibold">Work Category</label>
|
||||
<select name="category" class="form-select">
|
||||
|
||||
<option value="all">All Categories</option>
|
||||
|
||||
<option value="tr" {% if category_val=='tr' %}selected{% endif %}>
|
||||
Trench Excavation
|
||||
</option>
|
||||
|
||||
<option value="mh" {% if category_val=='mh' %}selected{% endif %}>
|
||||
Manhole Excavation
|
||||
</option>
|
||||
|
||||
<option value="dc" {% if category_val=='dc' %}selected{% endif %}>
|
||||
Manhole Domestic Chamber
|
||||
</option>
|
||||
|
||||
<option value="laying" {% if category_val=='laying' %}selected{% endif %}>
|
||||
Pipe Laying
|
||||
</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex justify-content-end gap-2">
|
||||
|
||||
<!-- Preview -->
|
||||
<button type="submit" name="action" value="preview" class="btn btn-primary">
|
||||
<i class="bi bi-search"></i>
|
||||
Preview Report
|
||||
</button>
|
||||
|
||||
<!-- Download -->
|
||||
<button type="submit" name="action" value="download" class="btn btn-success">
|
||||
<i class="bi bi-download"></i>
|
||||
Download Excel Report
|
||||
</button>
|
||||
|
||||
<button type="reset" class="btn btn-secondary" id="resetBtn">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
Reset
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if tables %}
|
||||
{% set show_all = (not category_val) or category_val == 'all' %}
|
||||
<!-- Tabs -->
|
||||
<div class="card shadow-sm border-0 mt-4">
|
||||
<div class="card-header bg-light">
|
||||
<ul class="nav nav-pills">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link {% if show_all %}active{% endif %}" data-bs-toggle="tab"
|
||||
data-bs-target="#abstract">
|
||||
<i class="bi bi-file-earmark-text"></i> Abstract
|
||||
</button>
|
||||
</li>
|
||||
|
||||
{% if show_all or category_val == 'tr' %}
|
||||
<li class="nav-item">
|
||||
<button class="nav-link {% if category_val == 'tr' %}active{% endif %}" data-bs-toggle="tab"
|
||||
data-bs-target="#tr">
|
||||
<i class="bi bi-cone-striped"></i> Trench Excavation
|
||||
</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if show_all or category_val == 'mh' %}
|
||||
<li class="nav-item">
|
||||
<button class="nav-link {% if category_val == 'mh' %}active{% endif %}" data-bs-toggle="tab"
|
||||
data-bs-target="#mh">
|
||||
<i class="bi bi-nut"></i> Manhole Excavation
|
||||
</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if show_all or category_val == 'dc' %}
|
||||
<li class="nav-item">
|
||||
<button class="nav-link {% if category_val == 'dc' %}active{% endif %}" data-bs-toggle="tab"
|
||||
data-bs-target="#dc">
|
||||
<i class="bi bi-grid-3x3"></i> Manhole & Domestic Chambers Construction
|
||||
</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if show_all or category_val == 'laying' %}
|
||||
<li class="nav-item">
|
||||
<button class="nav-link {% if category_val == 'laying' %}active{% endif %}" data-bs-toggle="tab"
|
||||
data-bs-target="#laying">
|
||||
<i class="bi bi-bezier2"></i> Pipe Laying
|
||||
</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane fade {% if show_all %}show active{% endif %}" id="abstract">
|
||||
{{ abstract_html|safe }}
|
||||
</div>
|
||||
|
||||
{% if show_all or category_val == 'tr' %}
|
||||
<!-- Trench -->
|
||||
<div class="tab-pane fade {% if category_val == 'tr' %}show active{% endif %}" id="tr">
|
||||
{% if has_data.tr %}
|
||||
<div class="mb-3">
|
||||
<button onclick="deleteSelected('tr_client')" class="btn btn-danger">
|
||||
<i class="bi bi-trash"></i> Delete Selected
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="table-responsive border rounded shadow-sm">
|
||||
{{ tables.tr|safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if show_all or category_val == 'mh' %}
|
||||
<!-- MH -->
|
||||
<div class="tab-pane fade {% if category_val == 'mh' %}show active{% endif %}" id="mh">
|
||||
{% if has_data.mh %}
|
||||
<div class="mb-3">
|
||||
<button onclick="deleteSelected('mh_client')" class="btn btn-danger">
|
||||
<i class="bi bi-trash"></i> Delete Selected
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="table-responsive border rounded shadow-sm">
|
||||
{{ tables.mh|safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if show_all or category_val == 'dc' %}
|
||||
<!-- DC -->
|
||||
<div class="tab-pane fade {% if category_val == 'dc' %}show active{% endif %}" id="dc">
|
||||
{% if has_data.dc %}
|
||||
<div class="mb-3">
|
||||
<button onclick="deleteSelected('dc_client')" class="btn btn-danger">
|
||||
<i class="bi bi-trash"></i> Delete Selected
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="table-responsive border rounded shadow-sm">
|
||||
{{ tables.dc|safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if show_all or category_val == 'laying' %}
|
||||
<!-- Laying -->
|
||||
<div class="tab-pane fade {% if category_val == 'laying' %}show active{% endif %}" id="laying">
|
||||
{% if has_data.laying %}
|
||||
<div class="mb-3">
|
||||
<button onclick="deleteSelected('laying_client')" class="btn btn-danger">
|
||||
<i class="bi bi-trash"></i> Delete Selected
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="table-responsive border rounded shadow-sm">
|
||||
{{ tables.laying|safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const TAB_STORAGE_KEY = "clientReportActiveTab";
|
||||
|
||||
$(document).on("shown.bs.tab", '[data-bs-toggle="tab"]', function (e) {
|
||||
let target = $(e.target).attr("data-bs-target");
|
||||
if (target) sessionStorage.setItem(TAB_STORAGE_KEY, target);
|
||||
});
|
||||
|
||||
(function restoreActiveTab() {
|
||||
let target = sessionStorage.getItem(TAB_STORAGE_KEY);
|
||||
if (!target) return;
|
||||
let btn = document.querySelector(`[data-bs-toggle="tab"][data-bs-target="${target}"]`);
|
||||
if (btn) {
|
||||
bootstrap.Tab.getOrCreateInstance(btn).show();
|
||||
}
|
||||
})();
|
||||
|
||||
// Reset
|
||||
document.getElementById("resetBtn").addEventListener("click", function () {
|
||||
sessionStorage.removeItem(TAB_STORAGE_KEY);
|
||||
window.location.href = window.location.pathname;
|
||||
});
|
||||
$('.datatable').each(function () {
|
||||
try {
|
||||
$(this).DataTable({
|
||||
pageLength: 10,
|
||||
dom: 'Bfrtip',
|
||||
buttons: ['copy', 'csv', 'excel', 'print'],
|
||||
columnDefs: [
|
||||
{ orderable: false, targets: [0, -1, -2] } // Select, Update, Delete columns
|
||||
]
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("DataTable init failed for a table:", err);
|
||||
}
|
||||
});
|
||||
$(document).on("change", ".select-all-checkbox", function () {
|
||||
let model = $(this).data("model");
|
||||
$(`.row-check[data-model="${model}"]`).prop("checked", this.checked);
|
||||
});
|
||||
|
||||
$(document).on("change", ".row-check", function () {
|
||||
let model = $(this).data("model");
|
||||
let $rows = $(`.row-check[data-model="${model}"]`);
|
||||
let allChecked = $rows.length > 0 && $rows.length === $rows.filter(":checked").length;
|
||||
$(`.select-all-checkbox[data-model="${model}"]`).prop("checked", allChecked);
|
||||
});
|
||||
|
||||
// SINGLE DELETE
|
||||
$(document).on("click", ".delete-btn", function () {
|
||||
let id = $(this).data("id");
|
||||
let model = $(this).data("model");
|
||||
|
||||
if (!confirm("Are you sure you want to delete this record?")) return;
|
||||
|
||||
fetch("/file/delete_records", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ model: model, ids: [id] })
|
||||
})
|
||||
.then(res => res.json().then(data => ({ ok: res.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.status === "success") {
|
||||
alert("Deleted Successfully");
|
||||
location.reload();
|
||||
} else {
|
||||
alert("Delete failed: " + (data.message || "Unknown error"));
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
alert("Delete request failed: " + err);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// GET IDS - scoped to a single table via data-model.
|
||||
function getSelectedIds(model) {
|
||||
let ids = [];
|
||||
$(`.row-check[data-model="${model}"]:checked`).each(function () {
|
||||
ids.push($(this).data("id"));
|
||||
});
|
||||
return ids;
|
||||
}
|
||||
window.deleteSelected = function (model) {
|
||||
let ids = getSelectedIds(model);
|
||||
if (ids.length === 0) return alert("Select records");
|
||||
|
||||
if (!confirm(`Delete ${ids.length} record(s)?`)) return;
|
||||
|
||||
fetch("/file/delete_records", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ model: model, ids: ids })
|
||||
})
|
||||
.then(res => res.json().then(data => ({ ok: res.ok, data })))
|
||||
.then(({ ok, data }) => {
|
||||
if (ok && data.status === "success") {
|
||||
alert("Deleted Successfully");
|
||||
location.reload();
|
||||
} else {
|
||||
alert("Delete failed: " + (data.message || "Unknown error"));
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
alert("Delete request failed: " + err);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -349,7 +349,7 @@
|
||||
// Reset
|
||||
document.getElementById("resetBtn").addEventListener("click", function () {
|
||||
sessionStorage.removeItem(TAB_STORAGE_KEY);
|
||||
location.reload();
|
||||
window.location.href = window.location.pathname;
|
||||
});
|
||||
|
||||
// LOCATION -> SUBCONTRACTOR CASCADE
|
||||
|
||||
Reference in New Issue
Block a user