Rapport-Laravel/resources/views/rcpareport/formwise.blade.php

304 lines
14 KiB
PHP

@extends('layouts.vertical', ['page_title' => 'Datatables'])
@section('css')
<!-- third party css -->
<link href="{{ asset('assets/libs/datatables/datatables.min.css') }}" rel="stylesheet" type="text/css" />
<link href="{{ asset('assets/libs/flatpickr/flatpickr.min.css') }}" rel="stylesheet" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/ag-grid-community@30.0.0/dist/ag-grid-community.min.js"></script>
<!-- third party css end -->
<meta name="csrf-token" content="{{ csrf_token() }}" />
<style type="text/css">
.ag-theme-alpine {
--ag-header-column-separator-display: block;
--ag-header-column-separator-height: 20%;
--ag-header-column-separator-width: 1px;
--ag-header-column-separator-color: rgb(0, 0, 0);
}
#myGrid {
height: calc(100vh - 200px);
}
</style>
@endsection
@section('content')
<!-- Start Content-->
<div class="container-fluid">
<!-- start page title -->
<div class="row">
<div class="col-md-6 p-2">
<h4 class="page-title">Form Wise RCPA Report</h4>
</div>
</div>
<!-- end page title -->
@if (session()->has('message'))
<div class="alert alert-success">
{{ session()->get('message') }}
</div>
@endif
@if (session()->has('error'))
<div class="alert alert-danger">
{{ session()->get('error') }}
</div>
@endif
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="row justify-content-between">
<div class="col-auto filter-section">
<form id="rcpaFilterForm" class="d-flex flex-wrap align-items-center gap-2" onsubmit="return false;">
<label for="form-select" class="me-2">Form:</label>
<div class="me-sm-3">
<select class="form-select my-1 my-lg-0" id="form-select" name="form_id">
<option value="">All Forms</option>
@if(isset($forms))
@foreach($forms as $f)
<option value="{{ $f->id }}">
{{ $f->title ?? $f->id }}
</option>
@endforeach
@endif
</select>
</div>
<label for="date-from" class="me-2">From:</label>
<input type="text" class="form-control datetime me-2" id="date-from" name="date_from" placeholder="YYYY-MM-DD" style="width:130px;">
<label for="date-to" class="me-2">To:</label>
<input type="text" class="form-control datetime me-2" id="date-to" name="date_to" placeholder="YYYY-MM-DD" style="width:130px;">
<button id="btn-fetch" class="btn btn-sm btn-info me-2" type="button" onclick="fetchRCPAReport()" style="font-weight:bold;">
Fetch
</button>
</form>
</div>
<div class="col-auto">
<div class="text-lg-end my-1 my-lg-0">
<div>
<button id="btn-export" class="btn btn-sm btn-primary"
style="margin-bottom: 5px; font-weight: bold">
Export to Excel
</button>
</div>
</div>
</div><!-- end col-->
</div>
</div>
</div> <!-- end card -->
</div> <!-- end col-->
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div id="myGrid" style="" class="ag-theme-alpine"></div>
</div> <!-- end card body-->
</div> <!-- end card -->
</div><!-- end col-->
</div>
<!-- end row-->
</div> <!-- container -->
@endsection
@section('script')
<!-- third party js -->
<script src="{{ asset('assets/libs/flatpickr/flatpickr.min.js') }}"></script>
<script src="{{ asset('assets/libs/bootstrap-datepicker/bootstrap-datepicker.min.js') }}"></script>
<script type="text/javascript">
$('.datetime').flatpickr({
dateFormat: "Y-m-d"
});
function rowSpan(params) {
return 20;
}
// Initial static columns
const initialColumnDefs = [
{ headerName: 'User Name', field: 'user_name', width: 150, pinned: 'left', filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'Employee Code', field: 'employee_code', width: 120, filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'Submition Date', field: 'record_date', width: 120, filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'Doctor Name', field: 'contact_id', width: 120, filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'MSL Code', field: 'msl_code', width: 120, filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'Speciality', field: 'speciality', width: 150, filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'Chemist Name', field: 'chemist_name', width: 150, filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'Chemist Type', field: 'type_of_chemist', width: 150, filter: 'agTextColumnFilter', floatingFilter: true },
{ headerName: 'Doctors Attached to Chemist', field: 'doctors_attached_to_chemist', width: 180, filter: 'agTextColumnFilter', floatingFilter: true },
];
let rowData = []
$('#btn-export').on('click', function() {
gridOptions.api.exportDataAsCsv();
});
const gridOptions = {
columnDefs: initialColumnDefs,
pagination: true,
paginationPageSize: 50,
defaultColDef: {
resizable: true,
sortable: true,
},
rowData: rowData,
domLayout: 'normal',
};
const gridDiv = document.querySelector('#myGrid');
new agGrid.Grid(gridDiv, gridOptions);
// Function to fetch RCPA report data
function fetchRCPAReport() {
let formId = $('#form-select').val();
let dateFrom = $('#date-from').val();
let dateTo = $('#date-to').val();
// Build query params
let params = {};
if (formId) params.form_id = formId;
if (dateFrom) params.date_from = dateFrom;
if (dateTo) params.date_to = dateTo;
// Show loader
$("#pageloader").fadeIn();
// Make AJAX call
$.ajax({
type: "GET",
url: '/rcpareport/ajaxformwise',
data: params,
success: function(data) {
let final_data = [];
let brandMap = {}; // { brandName: { competitors: Set<compName> } }
if(data.response && Array.isArray(data.response)) {
data.response.forEach(row => {
// 1. Pre-process row to map brands and find unique structure
let bMap = {};
if (row.brands && Array.isArray(row.brands)) {
row.brands.forEach(b => {
let bName = b.brand_name;
if (!bName) return;
// Build the brand map for grid columns
if (!brandMap[bName]) {
brandMap[bName] = { competitors: new Set() };
}
if (b.competitors && Array.isArray(b.competitors)) {
b.competitors.forEach(comp => {
if (comp && comp.competitor_name) {
brandMap[bName].competitors.add(comp.competitor_name);
}
});
}
// Build each row's per-brand map for Cipla and competitor data
if (!bMap[bName]) {
bMap[bName] = {
qty_cipla: b.cipla_qty,
val_cipla: b.cipla_value,
competitors: {}
};
}
// Add competitor data
if (b.competitors && Array.isArray(b.competitors)) {
b.competitors.forEach(comp => {
if (comp && comp.competitor_name) {
bMap[bName].competitors[comp.competitor_name] = {
qty: comp.competitors_qty,
val: comp.competitors_value
};
}
});
}
});
}
row.brands_map = bMap;
final_data.push(row);
});
}
// 2. Build Dynamic Column Definitions
let dynamicDefs = [];
Object.keys(brandMap).sort().forEach(brandName => {
let competitors = Array.from(brandMap[brandName].competitors).sort();
let brandChildren = [
{
headerName: 'Cipla Qty',
width: 100,
type: 'numericColumn',
valueGetter: function(params) {
return params.data.brands_map && params.data.brands_map[brandName] ? params.data.brands_map[brandName].qty_cipla : null;
}
},
{
headerName: 'Cipla Value',
width: 100,
type: 'numericColumn',
valueGetter: function(params) {
return params.data.brands_map && params.data.brands_map[brandName] ? params.data.brands_map[brandName].val_cipla : null;
}
}
];
competitors.forEach(compName => {
brandChildren.push({
headerName: compName,
children: [
{
headerName: 'Qty',
width: 100,
type: 'numericColumn',
valueGetter: function(params) {
try {
return params.data.brands_map[brandName].competitors[compName].qty;
} catch(e) { return null; }
}
},
{
headerName: 'Value',
width: 100,
type: 'numericColumn',
valueGetter: function(params) {
try {
return params.data.brands_map[brandName].competitors[compName].val;
} catch(e) { return null; }
}
}
]
});
});
dynamicDefs.push({
headerName: brandName,
children: brandChildren
});
});
// 3. Update Grid
let newColumnDefs = initialColumnDefs.concat(dynamicDefs);
gridOptions.api.setColumnDefs(newColumnDefs);
gridOptions.api.setRowData(final_data);
$("#pageloader").fadeOut();
},
error: function(xhr, status, error) {
console.error('Error loading form wise data:', error);
alert('Error loading data. Please try again.');
$("#pageloader").fadeOut();
}
});
}
// Initialize grid with empty data on page load
jQuery(document).ready(function($){
gridOptions.api.setRowData([]);
})
</script>
@endsection