fix some error
This commit is contained in:
@@ -273,7 +273,7 @@
|
|||||||
echo !empty($row["AA_AGENT"]) ? $row["AA_AGENT"] : "Not assigned";
|
echo !empty($row["AA_AGENT"]) ? $row["AA_AGENT"] : "Not assigned";
|
||||||
}
|
}
|
||||||
echo "</td></tr>";
|
echo "</td></tr>";
|
||||||
|
// var_dump($row);
|
||||||
echo "
|
echo "
|
||||||
<tr>
|
<tr>
|
||||||
<th>INTEREST</th>
|
<th>INTEREST</th>
|
||||||
@@ -289,7 +289,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>NUMBER OF INSTALLMENTS PAID</th>
|
<th>NUMBER OF INSTALLMENTS PAID</th>
|
||||||
<td>".$row["AA_NO_OF_PAYPAID"]. "</td>
|
<td>".$row["AA_BAL"] / $row["AA_INSTALLMENT"]. "</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>MATURITY DATE</th>
|
<th>MATURITY DATE</th>
|
||||||
|
|||||||
407
CONTENT/ROOT_URI/Admin/Due-updated-fi.php
Normal file
407
CONTENT/ROOT_URI/Admin/Due-updated-fi.php
Normal file
@@ -0,0 +1,407 @@
|
|||||||
|
<div class="">
|
||||||
|
<div class="text-right mb-3" style="margin-bottom: 15px;">
|
||||||
|
<button id="downloadPdf" class="btn btn-primary">Download Demand Sheet</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table table-striped table-bordered table-hover table-responsive">
|
||||||
|
<tr>
|
||||||
|
<th>SL</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>AC No</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Mobile</th>
|
||||||
|
<th>Account Create Date</th>
|
||||||
|
<th>Maturity Value</th>
|
||||||
|
<th>Balance</th>
|
||||||
|
<th>Total EMI</th>
|
||||||
|
<th>Total Paid EMI</th>
|
||||||
|
<th>Deu EMI Till Date</th>
|
||||||
|
<th>EMI Amount</th>
|
||||||
|
<th>Total Due Amount</th>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// function countCycles($cycle, $createDate, $totalInstallment) {
|
||||||
|
// $today = new DateTime();
|
||||||
|
// $startDate = new DateTime($createDate);
|
||||||
|
|
||||||
|
// $cycle = strtoupper(trim($cycle)); // normalize input (W/M/D)
|
||||||
|
|
||||||
|
// if ($cycle === "D") {
|
||||||
|
// // For daily cycles, count starts from the next day
|
||||||
|
// $startDate->modify('+1 day');
|
||||||
|
// if ($startDate > $today) {
|
||||||
|
// $count = 0;
|
||||||
|
// } else {
|
||||||
|
// $diff = $startDate->diff($today);
|
||||||
|
// $count = $diff->days;
|
||||||
|
// }
|
||||||
|
// } elseif ($cycle === "W") {
|
||||||
|
// // For weekly cycles, first payment is next week
|
||||||
|
// $startDate->modify('next monday'); // or use '+1 week' if you want exactly 7 days later
|
||||||
|
|
||||||
|
// if ($startDate > $today) {
|
||||||
|
// $count = 0;
|
||||||
|
// } else {
|
||||||
|
// $diff = $startDate->diff($today);
|
||||||
|
// $count = floor($diff->days / 7);
|
||||||
|
// }
|
||||||
|
// } elseif ($cycle === "M") {
|
||||||
|
// // For monthly cycles, first payment is next month
|
||||||
|
// $startDate->modify('first day of next month');
|
||||||
|
|
||||||
|
// if ($startDate > $today) {
|
||||||
|
// $count = 0;
|
||||||
|
// } else {
|
||||||
|
// $diff = $startDate->diff($today);
|
||||||
|
// $count = ($diff->y * 12) + $diff->m;
|
||||||
|
|
||||||
|
// // If we're in the same month but after the start date, add one
|
||||||
|
// if ($diff->y == 0 && $diff->m == 0 && $diff->d > 0) {
|
||||||
|
// $count++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// $count = 0; // unknown cycle
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Ensure count doesn't exceed total installments
|
||||||
|
// return min($count, $totalInstallment);
|
||||||
|
// }
|
||||||
|
function countCycles($cycle, $createDate, $totalInstallment, $accountType) {
|
||||||
|
$today = new DateTime();
|
||||||
|
$startDate = new DateTime($createDate);
|
||||||
|
|
||||||
|
$cycle = strtoupper(trim($cycle));
|
||||||
|
|
||||||
|
if ($cycle === "D") {
|
||||||
|
// দৈনিক চক্র: ক্রিয়েশন ডেট থেকেই শুরু
|
||||||
|
if($accountType === 'Recurring'){
|
||||||
|
$firstPaymentDate = clone $startDate; // সেই দিনই শুরু
|
||||||
|
} elseif($accountType === 'Loan') {
|
||||||
|
$firstPaymentDate = (clone $startDate)->modify('+1 day'); // পরের দিন থেকে
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($firstPaymentDate > $today) {
|
||||||
|
$count = 0;
|
||||||
|
} else {
|
||||||
|
$diff = $firstPaymentDate->diff($today);
|
||||||
|
$count = $diff->days + 1; // +1 because diff->days doesn't include start day
|
||||||
|
}
|
||||||
|
} elseif ($cycle === "W") {
|
||||||
|
if($accountType === 'Recurring'){
|
||||||
|
$firstPaymentDate = clone $startDate;
|
||||||
|
}elseif($accountType === 'Loan'){
|
||||||
|
// সাপ্তাহিক চক্র: ৭ দিন পরে প্রথম EMI
|
||||||
|
$firstPaymentDate = (clone $startDate)->modify('+7 days');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($firstPaymentDate > $today) {
|
||||||
|
$count = 0;
|
||||||
|
} else {
|
||||||
|
$diff = $firstPaymentDate->diff($today);
|
||||||
|
$count = floor($diff->days / 7) + 1;
|
||||||
|
}
|
||||||
|
} elseif ($cycle === "M") {
|
||||||
|
if($accountType === 'Recurring'){
|
||||||
|
$firstPaymentDate = clone $startDate;
|
||||||
|
}elseif($accountType === 'Loan'){
|
||||||
|
// মাসিক চক্র: পরের মাসের同一天 প্রথম EMI
|
||||||
|
$firstPaymentDate = (clone $startDate)->modify('+1 month');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// যদি পরের মাসে同一天 না থাকে (যেমন 31st Jan থেকে 28/29th Feb)
|
||||||
|
if ($firstPaymentDate->format('d') != $startDate->format('d')) {
|
||||||
|
$firstPaymentDate->modify('last day of this month');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($firstPaymentDate > $today) {
|
||||||
|
$count = 0;
|
||||||
|
} else {
|
||||||
|
$count = 1; // প্রথম EMI already due
|
||||||
|
$nextPaymentDate = clone $firstPaymentDate;
|
||||||
|
|
||||||
|
// পরের মাসগুলির জন্য গণনা
|
||||||
|
while ($nextPaymentDate <= $today) {
|
||||||
|
$nextPaymentDate->modify('+1 month');
|
||||||
|
|
||||||
|
// তারিখ adjust করাが必要 হলে
|
||||||
|
if ($nextPaymentDate->format('d') != $firstPaymentDate->format('d')) {
|
||||||
|
$nextPaymentDate->modify('last day of this month');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($nextPaymentDate <= $today) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return min($count, $totalInstallment);
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn = new mysqli($GLOBALS['host'], $GLOBALS['user'], $GLOBALS['pass'], $GLOBALS['db']);
|
||||||
|
if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); }
|
||||||
|
$totalLoanEMIAmount = 0;
|
||||||
|
$totalDeuEMITillDate = 0;
|
||||||
|
|
||||||
|
$totalRecurringEMIAmount = 0;
|
||||||
|
$totalDeuInstallTillDate = 0;
|
||||||
|
|
||||||
|
$agent_id = $_SESSION['user_id'];
|
||||||
|
$types = ['Loan', 'Recurring'];
|
||||||
|
$pdfData = [];
|
||||||
|
$sl = 1;
|
||||||
|
|
||||||
|
// Grand total for PDF
|
||||||
|
$grandTotal = [
|
||||||
|
'accounts' => 0,
|
||||||
|
'paidInstallments' => 0,
|
||||||
|
'dueInstallments' => 0,
|
||||||
|
'dueAmount' => 0
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach($types as $type){
|
||||||
|
$typeLike = "%$type%";
|
||||||
|
if($_SESSION['type']==='admin'){
|
||||||
|
$sql = "SELECT * FROM `" . $GLOBALS['arif_ac'] . "` WHERE `AA_TYPE` LIKE ? AND (`STATUS` IS NULL OR (`STATUS`!='closed' AND `STATUS`!='matured')) ORDER BY `AA_ID` DESC";
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
$stmt->bind_param("s", $typeLike);
|
||||||
|
} elseif($_SESSION['type']==='agent'){
|
||||||
|
$sql = "SELECT * FROM `" . $GLOBALS['arif_ac'] . "` WHERE `AA_TYPE` LIKE ? AND (`STATUS` IS NULL OR (`STATUS`!='closed' AND `STATUS`!='matured')) AND `AA_AGENT`=? ORDER BY `AA_ID` DESC";
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
$stmt->bind_param("ss", $typeLike, $agent_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
|
||||||
|
if($result->num_rows>0){
|
||||||
|
echo "<tr><td colspan='13' style='text-align:center; font-weight:bold; background:#f0f0f0;'>$type Demand</td></tr>";
|
||||||
|
|
||||||
|
while($row = $result->fetch_assoc()){
|
||||||
|
$totalDueAmt = $row['AA_BAL'];
|
||||||
|
|
||||||
|
|
||||||
|
if ($row['AA_INSTALLMENT'] > 0) {
|
||||||
|
$paidInst = ($row['AA_MATURE_VALUE'] + $row['AA_BAL']) / $row['AA_INSTALLMENT'];
|
||||||
|
$paidInst = number_format($paidInst, 2);
|
||||||
|
|
||||||
|
$remainInst = abs($row['AA_BAL']) / $row['AA_INSTALLMENT'];
|
||||||
|
$remainInst = number_format($remainInst, 2);
|
||||||
|
} else {
|
||||||
|
$paidInst = 0; // বা অন্য লজিক
|
||||||
|
$remainInst = 0;
|
||||||
|
}
|
||||||
|
if($row['AA_TYPE'] === 'Loan'){
|
||||||
|
$paidInstallment = ($row['AA_MATURE_VALUE'] + $row['AA_BAL']) / $row['AA_INSTALLMENT'];
|
||||||
|
$paidInstallment = number_format($paidInstallment, 2, '.', '');
|
||||||
|
|
||||||
|
$deuEMITillDate = countCycles($row['AA_ACTYPE'], $row['AA_DATE'], $row['AA_NO_OF_PAYMENT'], $row['AA_TYPE']) - $paidInstallment;
|
||||||
|
$deuEMITillDate = number_format($deuEMITillDate, 2, '.', '');
|
||||||
|
|
||||||
|
if($deuEMITillDate > 0){
|
||||||
|
// echo $deuEMITillDate;
|
||||||
|
$totalDeuEMITillDate += $deuEMITillDate; // এখানে যোগ হচ্ছে
|
||||||
|
$totalLoanEMIAmount += $row['AA_INSTALLMENT'];
|
||||||
|
}
|
||||||
|
}elseif($row['AA_TYPE'] === 'Recurring'){
|
||||||
|
$paidInstallment = $row['AA_BAL'] / $row['AA_INSTALLMENT'];
|
||||||
|
$paidInstallment = number_format($paidInstallment, 2, '.', '');
|
||||||
|
|
||||||
|
$deuEMITillDate = countCycles($row['AA_ACTYPE'], $row['AA_DATE'], $row['AA_NO_OF_PAYMENT'], $row['AA_TYPE']) - $paidInstallment;
|
||||||
|
// $deuEMITillDate = abs($deuEMITillDate);
|
||||||
|
$deuEMITillDate = number_format($deuEMITillDate, 2, '.', '');
|
||||||
|
|
||||||
|
if($deuEMITillDate > 0){
|
||||||
|
// echo $deuEMITillDate;
|
||||||
|
$totalDeuInstallTillDate += $deuEMITillDate; // এখানে যোগ হচ্ছে
|
||||||
|
$totalRecurringEMIAmount += $row['AA_INSTALLMENT'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// HTML table row
|
||||||
|
if($deuEMITillDate > 0){
|
||||||
|
echo "<tr>
|
||||||
|
<td>".$sl."</td>
|
||||||
|
<td>".$row['AA_ACTYPE'].", ".$row['AA_TYPE']."</td>
|
||||||
|
<td>".$row['AA_ACNO']."</td>
|
||||||
|
<td>".$row['AA_NAME']."</td>
|
||||||
|
<td>".$row['AA_PHONE']."</td>
|
||||||
|
<td>".$row['AA_DATE']."</td>
|
||||||
|
<td>".$row['AA_MATURE_VALUE']."</td>
|
||||||
|
<td>".$row['AA_BAL']."</td>
|
||||||
|
<td>".$row['AA_NO_OF_PAYMENT']."</td>
|
||||||
|
<td>".$paidInstallment."</td>
|
||||||
|
<td>".$deuEMITillDate."</td>
|
||||||
|
<td>".$row['AA_INSTALLMENT']."</td>
|
||||||
|
<td>".$totalDueAmt."</td>
|
||||||
|
|
||||||
|
</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// <td>".$remainInst."</td> <td>".$row['AA_NO_OF_PAYMENT']."</td>
|
||||||
|
// PDF simplified row
|
||||||
|
// "SL","NAME ","MOBILE NO", "CYCLE", "ACCOUNT NO","EMI PAID","EMI DUE", "EMI AMOUNT", "CUSTOMER. SIGN"
|
||||||
|
if($deuEMITillDate > 0){
|
||||||
|
$pdfData[] = [
|
||||||
|
$type,
|
||||||
|
$sl,
|
||||||
|
$row['AA_NAME'], // NAME OF ACCOUNT HOLDER
|
||||||
|
$row['AA_PHONE'], // MOBILE NO (blank)
|
||||||
|
$row['AA_ACTYPE'], // EMI Cycle
|
||||||
|
$row['AA_ACNO'], // ACCOUNT NO
|
||||||
|
$paidInstallment, // NO OF INSTALLMENT PAID
|
||||||
|
$deuEMITillDate, // NO OF INSTALLMENT DUE
|
||||||
|
$row['AA_INSTALLMENT'], // EMI AMOUNT
|
||||||
|
// $totalDueAmt, // TOTAL DUE AMOUNT
|
||||||
|
"" // CUSTOMER SIGNATURE
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update grand total
|
||||||
|
$grandTotal['accounts']++;
|
||||||
|
$grandTotal['paidInstallments'] += $paidInstallment;
|
||||||
|
$grandTotal['dueInstallments'] += $deuEMITillDate;
|
||||||
|
$grandTotal['dueAmount'] += $totalDueAmt;
|
||||||
|
|
||||||
|
$sl++;
|
||||||
|
|
||||||
|
// echo $dueInst . '<br>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$conn->close();
|
||||||
|
$grandTotal['totalNumberOfLoanEMI'] = $totalDeuEMITillDate;
|
||||||
|
$grandTotal['totalNumberOfRecurringEMI'] = $totalDeuInstallTillDate;
|
||||||
|
$grandTotal['totalLoanEMIAmount'] = $totalLoanEMIAmount;
|
||||||
|
$grandTotal['totalRecurringEMIAmount'] = $totalRecurringEMIAmount;
|
||||||
|
// echo "<br>Total Due EMI Till Date (Loan): ".$totalDeuEMITillDate;
|
||||||
|
// echo "<br>Total Due Installment Till Date (Recurring): ".$totalDeuInstallTillDate;
|
||||||
|
|
||||||
|
?>
|
||||||
|
</table>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.28/jspdf.plugin.autotable.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
document.getElementById('downloadPdf').addEventListener('click', function() {
|
||||||
|
const { jsPDF } = window.jspdf;
|
||||||
|
const doc = new jsPDF('p', 'pt', 'a4');
|
||||||
|
|
||||||
|
const userType = "<?php echo $_SESSION['type']; ?>";
|
||||||
|
const userName = "<?php echo $_SESSION['name']; ?>";
|
||||||
|
const now = new Date();
|
||||||
|
const dateTime = now.toLocaleDateString() + " " + now.toLocaleTimeString();
|
||||||
|
const titleText = "Grafin Ventures Demand Sheet";
|
||||||
|
|
||||||
|
const pdfData = <?php echo json_encode($pdfData); ?>;
|
||||||
|
const grandTotal = <?php echo json_encode($grandTotal); ?>;
|
||||||
|
|
||||||
|
const logo = new Image();
|
||||||
|
logo.src = '/asset/images/new_logo2.jpg';
|
||||||
|
logo.onload = () => addHeader();
|
||||||
|
logo.onerror = () => addHeader();
|
||||||
|
|
||||||
|
function addHeader(){
|
||||||
|
try { doc.addImage(logo, 'PNG', 40, 30, 40, 40); } catch(e) {}
|
||||||
|
doc.setFontSize(16);
|
||||||
|
doc.text(titleText, 100, 50);
|
||||||
|
doc.setFontSize(10);
|
||||||
|
doc.text(`Generated on: ${dateTime}`, 40, 80);
|
||||||
|
doc.text(`User Type: ${userType}`, 40, 95);
|
||||||
|
doc.text(`Agen Name: ${userName}`, 40, 110);
|
||||||
|
|
||||||
|
let y = 130;
|
||||||
|
|
||||||
|
const headers = ["SL","NAME ","MOBILE NO", "CYCLE", "ACCOUNT NO","EMI PAID","EMI DUE", "EMI AMOUNT", "CUSTOMER. SIGN"];
|
||||||
|
let currentType = '';
|
||||||
|
let rows = [];
|
||||||
|
|
||||||
|
pdfData.forEach(row=>{
|
||||||
|
if(row[0] !== currentType){
|
||||||
|
if(rows.length>0){
|
||||||
|
doc.autoTable({
|
||||||
|
head:[headers],
|
||||||
|
body:rows,
|
||||||
|
startY:y,
|
||||||
|
styles:{
|
||||||
|
fontSize:7,
|
||||||
|
cellPadding:3,
|
||||||
|
lineWidth: 0.1, // border width
|
||||||
|
lineColor: [0, 0, 0] // black border color
|
||||||
|
},
|
||||||
|
headStyles:{ fillColor: false, textColor: 0 },
|
||||||
|
bodyStyles:{ valign:'middle', fillColor: false },
|
||||||
|
alternateRowStyles: { fillColor: false },
|
||||||
|
columnStyles: { 1: { cellWidth: 110 } }
|
||||||
|
});
|
||||||
|
y = doc.lastAutoTable.finalY + 10;
|
||||||
|
rows=[];
|
||||||
|
}
|
||||||
|
currentType = row[0];
|
||||||
|
doc.setFont(undefined,'bold');
|
||||||
|
doc.text(`${currentType} Demand`,40,y);
|
||||||
|
y+=15;
|
||||||
|
doc.setFont(undefined,'normal');
|
||||||
|
}
|
||||||
|
rows.push(row.slice(1));
|
||||||
|
});
|
||||||
|
|
||||||
|
if(rows.length>0){
|
||||||
|
doc.autoTable({
|
||||||
|
head:[headers],
|
||||||
|
body:rows,
|
||||||
|
startY:y,
|
||||||
|
styles:{
|
||||||
|
fontSize:7,
|
||||||
|
cellPadding:3,
|
||||||
|
lineWidth: 0.1, // border width
|
||||||
|
lineColor: [0, 0, 0] // black border color
|
||||||
|
},
|
||||||
|
headStyles:{ fillColor: false, textColor: 0 },
|
||||||
|
bodyStyles:{ valign:'middle', fillColor: false },
|
||||||
|
alternateRowStyles: { fillColor: false },
|
||||||
|
columnStyles: { 1: { cellWidth: 110 } }
|
||||||
|
});
|
||||||
|
y = doc.lastAutoTable.finalY + 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grand Total totalNumberOfLoanEMI totalNumberOfRecurringEMI totalLoanEMIAmount totalRecurringEMIAmount
|
||||||
|
doc.setFont(undefined, 'bold');
|
||||||
|
let lineHeight = 12; // fixed gap between lines
|
||||||
|
let currentY = y-8;
|
||||||
|
|
||||||
|
doc.text(`Total Number of Loan EMI: ${grandTotal.totalNumberOfLoanEMI}`, 20, currentY);
|
||||||
|
|
||||||
|
currentY += lineHeight;
|
||||||
|
doc.text(`Total Number of Recurring Installment: ${grandTotal.totalNumberOfRecurringEMI}`, 20, currentY);
|
||||||
|
|
||||||
|
currentY += lineHeight;
|
||||||
|
doc.text(`Grand Total Loan EMI Amount: ${grandTotal.totalLoanEMIAmount.toLocaleString('en-IN',{minimumFractionDigits:2, maximumFractionDigits:2})}`, 20, currentY);
|
||||||
|
|
||||||
|
currentY += lineHeight;
|
||||||
|
doc.text(`Grand Total Recurring EMI Amount: ${grandTotal.totalRecurringEMIAmount.toLocaleString('en-IN',{minimumFractionDigits:2, maximumFractionDigits:2})}`, 20, currentY);
|
||||||
|
|
||||||
|
// Footer with page numbers
|
||||||
|
const pageCount = doc.internal.getNumberOfPages();
|
||||||
|
for(let i=1;i<=pageCount;i++){
|
||||||
|
doc.setPage(i);
|
||||||
|
doc.setFontSize(9);
|
||||||
|
doc.setFont(undefined,'normal');
|
||||||
|
// doc.text(`Generated by Loan Portal - Confidential`,40,doc.internal.pageSize.height-20);
|
||||||
|
doc.text(`Page ${i} of ${pageCount}`,doc.internal.pageSize.width-60,doc.internal.pageSize.height-20);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.save(`Demand_Sheet_${userType}_${userName}_${now.toISOString().slice(0,10)}.pdf`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -365,7 +365,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
doc.setPage(i);
|
doc.setPage(i);
|
||||||
doc.setFontSize(9);
|
doc.setFontSize(9);
|
||||||
doc.setFont(undefined,'normal');
|
doc.setFont(undefined,'normal');
|
||||||
doc.text(`Generated by Loan Portal - Confidential`,40,doc.internal.pageSize.height-20);
|
// doc.text(`Generated by Loan Portal - Confidential`,40,doc.internal.pageSize.height-20);
|
||||||
doc.text(`Page ${i} of ${pageCount}`,doc.internal.pageSize.width-60,doc.internal.pageSize.height-20);
|
doc.text(`Page ${i} of ${pageCount}`,doc.internal.pageSize.width-60,doc.internal.pageSize.height-20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
74
CONTENT/ROOT_URI/Admin/agent-targets-updated.php
Normal file
74
CONTENT/ROOT_URI/Admin/agent-targets-updated.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
$conn = new mysqli($GLOBALS['host'], $GLOBALS['user'], $GLOBALS['pass'], $GLOBALS['db']);
|
||||||
|
$conn->set_charset("utf8");
|
||||||
|
if ($conn->connect_error) {
|
||||||
|
die("Connection failed: " . $conn->connect_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get agent list
|
||||||
|
$getAgentListsQuery = "SELECT * FROM " . $GLOBALS['arif_users'];
|
||||||
|
$agentResult = $conn->query($getAgentListsQuery);
|
||||||
|
$agentList = [];
|
||||||
|
if ($agentResult && $agentResult->num_rows > 0) {
|
||||||
|
while ($row = $agentResult->fetch_assoc()) {
|
||||||
|
$agentList[] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$collectableLoanAmount = isset($_POST['COLLECTABLE_LOAN_AMOUNT']) ? floatval($_POST['COLLECTABLE_LOAN_AMOUNT']) : 0;
|
||||||
|
$collectableRecurringAmount = isset($_POST['COLLECTABLE_RECURRING_AMOUNT']) ? floatval($_POST['COLLECTABLE_RECURRING_AMOUNT']) : 0;
|
||||||
|
$collectableAgent = isset($_POST['COLLECTABLE_AGENT']) ? $_POST['COLLECTABLE_AGENT'] : null;
|
||||||
|
|
||||||
|
if (($collectableLoanAmount > 0 || $collectableRecurringAmount > 0) && $collectableAgent) {
|
||||||
|
$stmt = $conn->prepare("
|
||||||
|
INSERT INTO agent_collections (
|
||||||
|
agent,
|
||||||
|
collectable_loan_amount,
|
||||||
|
collected_loan_amount,
|
||||||
|
collectable_recurring_amount,
|
||||||
|
collected_recurring_amount,
|
||||||
|
date
|
||||||
|
) VALUES (?, ?, 0, ?, 0, CURDATE())
|
||||||
|
");
|
||||||
|
$stmt->bind_param("sdd", $collectableAgent, $collectableLoanAmount, $collectableRecurringAmount);
|
||||||
|
|
||||||
|
if ($stmt->execute()) {
|
||||||
|
echo "<div class='alert alert-success'>Target assigned successfully!</div>";
|
||||||
|
} else {
|
||||||
|
echo "<div class='alert alert-danger'>Error: " . $stmt->error . "</div>";
|
||||||
|
}
|
||||||
|
$stmt->close();
|
||||||
|
} else {
|
||||||
|
echo "<div class='alert alert-warning'>Please enter a valid target amount and select an agent.</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h2>Agent Collection Targets</h2>
|
||||||
|
<form method="post" style="display: flex; flex-direction: column; gap: 15px;">
|
||||||
|
<div>
|
||||||
|
<label for="COLLECTABLE_LOAN_AMOUNT">Loan Target Amount:</label>
|
||||||
|
<input id="COLLECTABLE_LOAN_AMOUNT" class="form-control" name="COLLECTABLE_LOAN_AMOUNT" type="text" placeholder="Enter Loan Amount" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="COLLECTABLE_RECURRING_AMOUNT">Recurring Target Amount:</label>
|
||||||
|
<input id="COLLECTABLE_RECURRING_AMOUNT" class="form-control" name="COLLECTABLE_RECURRING_AMOUNT" type="text" placeholder="Enter Recurring Amount" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="COLLECTABLE_AGENT">Assign To Agent:</label>
|
||||||
|
<select class="form-control" name="COLLECTABLE_AGENT" id="COLLECTABLE_AGENT">
|
||||||
|
<?php
|
||||||
|
foreach($agentList as $agent){
|
||||||
|
echo '<option value="'.$agent['user_id'].'">'.$agent['user_id'].' / '.$agent['user_name'].'</option>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" type="submit">Assign Target</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// ---- Default date range ----
|
// ---- Default date range ----
|
||||||
$today = date("Y-m-d");
|
$today = date("Y-m-d");
|
||||||
$monthStart = date("Y-m-01");
|
$monthStart = date("Y-m-01");
|
||||||
$monthEnd = date("Y-m-t"); // Gets last day of current month (e.g., 2023-10-31)
|
$monthEnd = date("Y-m-t"); // Gets last day of current month
|
||||||
$dFrom = $_GET['dFrom'] ?? $monthStart;
|
$dFrom = $_GET['dFrom'] ?? $monthStart;
|
||||||
$dTo = $_GET['dTo'] ?? $monthEnd;
|
$dTo = $_GET['dTo'] ?? $monthEnd;
|
||||||
?>
|
?>
|
||||||
@@ -37,8 +37,12 @@ function maturity_report($dateFrom, $dateTo) {
|
|||||||
$conn = new mysqli($GLOBALS['host'], $GLOBALS['user'], $GLOBALS['pass'], $GLOBALS['db']);
|
$conn = new mysqli($GLOBALS['host'], $GLOBALS['user'], $GLOBALS['pass'], $GLOBALS['db']);
|
||||||
if ($conn->connect_error) die("Connection failed: " . $conn->connect_error);
|
if ($conn->connect_error) die("Connection failed: " . $conn->connect_error);
|
||||||
|
|
||||||
// ---- Next month maturity filter ----
|
// ---- Fetch matured accounts ----
|
||||||
$sql = "SELECT * FROM ".$GLOBALS['arif_ac']." WHERE DATE_FORMAT(AA_DATE_MATURE, '%Y-%m-%d') BETWEEN '".$dateFrom."' AND '".$dateTo."' AND AA_TYPE = 'Recurring' ORDER BY AA_DATE_MATURE ASC";
|
$sql = "SELECT * FROM ".$GLOBALS['arif_ac']."
|
||||||
|
WHERE DATE_FORMAT(AA_DATE_MATURE, '%Y-%m-%d')
|
||||||
|
BETWEEN '".$dateFrom."' AND '".$dateTo."'
|
||||||
|
AND AA_TYPE = 'Recurring'
|
||||||
|
ORDER BY AA_DATE_MATURE ASC";
|
||||||
|
|
||||||
$result = $conn->query($sql);
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
@@ -67,19 +71,14 @@ function maturity_report($dateFrom, $dateTo) {
|
|||||||
if ($result && $result->num_rows > 0) {
|
if ($result && $result->num_rows > 0) {
|
||||||
while($row = $result->fetch_assoc()) {
|
while($row = $result->fetch_assoc()) {
|
||||||
|
|
||||||
// Calculate installments
|
// Installment calculation
|
||||||
$paid_installments = floor($row['AA_BAL'] / $row['AA_INSTALLMENT']);
|
$paid_installments = floor($row['AA_BAL'] / $row['AA_INSTALLMENT']);
|
||||||
$pending_installments = $row['AA_NO_OF_PAYMENT'] - $paid_installments;
|
$pending_installments = $row['AA_NO_OF_PAYMENT'] - $paid_installments;
|
||||||
|
|
||||||
if ($pending_installments <= 0) {
|
// ✅ Show only fully paid accounts
|
||||||
// Fully matured
|
if ($pending_installments == 0 && $paid_installments == $row['AA_NO_OF_PAYMENT']) {
|
||||||
$payout = $row['AA_MATURE_VALUE'];
|
$payout = $row['AA_MATURE_VALUE'];
|
||||||
} else {
|
$grandTotal += $payout;
|
||||||
// Not fully paid, only balance is eligible
|
|
||||||
$payout = $row['AA_BAL'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$grandTotal += $row['AA_MATURE_VALUE'];
|
|
||||||
|
|
||||||
echo "
|
echo "
|
||||||
<tr>
|
<tr>
|
||||||
@@ -93,6 +92,7 @@ function maturity_report($dateFrom, $dateTo) {
|
|||||||
<td>".$row['AA_DATE_MATURE']."</td>
|
<td>".$row['AA_DATE_MATURE']."</td>
|
||||||
</tr>";
|
</tr>";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
echo "<tr><td colspan='8' class='text-center text-muted'>No matured accounts found</td></tr>";
|
echo "<tr><td colspan='8' class='text-center text-muted'>No matured accounts found</td></tr>";
|
||||||
}
|
}
|
||||||
|
|||||||
339
CONTENT/ROOT_URI/Agent/Dashboard-updated.php
Normal file
339
CONTENT/ROOT_URI/Agent/Dashboard-updated.php
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['user_id']) || empty($_SESSION['user_id'])) {
|
||||||
|
echo "<script>window.location.href = '/Agent/agent-login'</script>";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn = new mysqli($GLOBALS['host'], $GLOBALS['user'], $GLOBALS['pass'], $GLOBALS['db']);
|
||||||
|
if ($conn->connect_error) {
|
||||||
|
die("Connection failed: " . $conn->connect_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$today = date("Y-m-d");
|
||||||
|
$userId = $_SESSION['user_id'];
|
||||||
|
$message = "";
|
||||||
|
|
||||||
|
/* ---------------- Loan & Recurring Transactions (Today) ---------------- */
|
||||||
|
$sqlLoan = "SELECT SUM(AT_AMOUNT) as total
|
||||||
|
FROM {$GLOBALS['arif_tran']}
|
||||||
|
WHERE AT_ADMIN = '$userId'
|
||||||
|
AND DATE(AT_TIMESTAMP) = '$today'
|
||||||
|
AND AT_ACID LIKE '%L%'";
|
||||||
|
$resLoan = $conn->query($sqlLoan);
|
||||||
|
$totalLoan = $resLoan->fetch_assoc()['total'] ?? 0;
|
||||||
|
|
||||||
|
$sqlRecurring = "SELECT SUM(AT_AMOUNT) as total
|
||||||
|
FROM {$GLOBALS['arif_tran']}
|
||||||
|
WHERE AT_ADMIN = '$userId'
|
||||||
|
AND DATE(AT_TIMESTAMP) = '$today'
|
||||||
|
AND AT_ACID LIKE '%R%'";
|
||||||
|
$resRecurring = $conn->query($sqlRecurring);
|
||||||
|
$totalRecurring = $resRecurring->fetch_assoc()['total'] ?? 0;
|
||||||
|
|
||||||
|
/* ---------------- Get Today's Target ---------------- */
|
||||||
|
$targetSql = "SELECT * FROM agent_collections WHERE agent = '$userId' AND date = '$today'";
|
||||||
|
$targetResult = $conn->query($targetSql);
|
||||||
|
$targetRows = $targetResult->fetch_all(MYSQLI_ASSOC);
|
||||||
|
|
||||||
|
$collectableLoan = $targetRows[0]['collectable_loan_amount'] ?? 0;
|
||||||
|
$collectableRecurring = $targetRows[0]['collectable_recurring_amount'] ?? 0;
|
||||||
|
|
||||||
|
$remainingLoan = max($collectableLoan - $totalLoan, 0);
|
||||||
|
$remainingRecurring = max($collectableRecurring - $totalRecurring, 0);
|
||||||
|
|
||||||
|
$loanPercent = $collectableLoan > 0 ? ($totalLoan / $collectableLoan) * 100 : 0;
|
||||||
|
$recurringPercent = $collectableRecurring > 0 ? ($totalRecurring / $collectableRecurring) * 100 : 0;
|
||||||
|
|
||||||
|
/* ---------------- Save Collection ---------------- */
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_collection'])) {
|
||||||
|
$rowId = intval($_POST['row_id']);
|
||||||
|
$collectedLoan = $totalLoan;
|
||||||
|
$collectedRecurring = $totalRecurring;
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("UPDATE agent_collections
|
||||||
|
SET collected_loan_amount = ?, collected_recurring_amount = ?
|
||||||
|
WHERE id = ? AND agent = ? AND date = ?");
|
||||||
|
$stmt->bind_param("ddiss", $collectedLoan, $collectedRecurring, $rowId, $userId, $today);
|
||||||
|
|
||||||
|
if ($stmt->execute()) {
|
||||||
|
$message = "<p class='success-msg'>✅ Collection saved successfully!</p>";
|
||||||
|
} else {
|
||||||
|
$message = "<p class='error-msg'>❌ Failed to save collection!</p>";
|
||||||
|
}
|
||||||
|
$stmt->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------- Last 10 Days Report ---------------- */
|
||||||
|
$repStmt = "SELECT * FROM agent_collections WHERE agent = '$userId' ORDER BY date DESC LIMIT 10";
|
||||||
|
$reportsStmt = $conn->query($repStmt);
|
||||||
|
$reportRows = $reportsStmt->fetch_all(MYSQLI_ASSOC);
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container" style="margin-bottom: 105px;">
|
||||||
|
<h3 class="welcome-text">
|
||||||
|
Welcome, <?= htmlspecialchars($_SESSION['name']) ?> 👋
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<?= $message ?>
|
||||||
|
|
||||||
|
<div class="dashboard-total-section">
|
||||||
|
<!-- Loan Box -->
|
||||||
|
<div class="card-box highlight">
|
||||||
|
<h3>₹ <?= number_format($totalLoan, 2) ?></h3>
|
||||||
|
<p>Loan Collection</p>
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" style="width: <?= $loanPercent ?>%;"></div>
|
||||||
|
</div>
|
||||||
|
<small><?= round($loanPercent, 2) ?>% Completed</small>
|
||||||
|
<div class="remaining-text">
|
||||||
|
Target: ₹ <?= number_format($collectableLoan, 2) ?> |
|
||||||
|
Remaining: ₹ <?= number_format($remainingLoan, 2) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Recurring Box -->
|
||||||
|
<div class="card-box normal">
|
||||||
|
<h3>₹ <?= number_format($totalRecurring, 2) ?></h3>
|
||||||
|
<p>Recurring Collection</p>
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" style="width: <?= $recurringPercent ?>%;"></div>
|
||||||
|
</div>
|
||||||
|
<small><?= round($recurringPercent, 2) ?>% Completed</small>
|
||||||
|
<div class="remaining-text">
|
||||||
|
Target: ₹ <?= number_format($collectableRecurring, 2) ?> |
|
||||||
|
Remaining: ₹ <?= number_format($remainingRecurring, 2) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Buttons -->
|
||||||
|
<div style="display: flex; flex-direction: row; width: 100%; justify-content: space-between; margin-top: 20px;">
|
||||||
|
<a class="btn btn-primary w-100" href="/Agent/Receive">
|
||||||
|
<i class="fa-solid fa-credit-card"></i> Receive New Payment
|
||||||
|
</a>
|
||||||
|
<?php if (!empty($targetRows)) : ?>
|
||||||
|
<form method="post" class="w-100">
|
||||||
|
<input type="hidden" name="save_collection" value="1">
|
||||||
|
<input type="hidden" name="row_id" value="<?= $targetRows[0]['id'] ?>">
|
||||||
|
<button type="submit" class="btn btn-success w-100">
|
||||||
|
<i class="fa-solid fa-save"></i> Save Collection
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Report Section -->
|
||||||
|
<?php if (!empty($reportRows)) : ?>
|
||||||
|
<div class="report-section">
|
||||||
|
<h4 class="report-title">📊 Last 10 Days Report</h4>
|
||||||
|
<div class="report-cards">
|
||||||
|
<?php foreach ($reportRows as $report): ?>
|
||||||
|
<?php
|
||||||
|
$loanPercentDone = $report['collectable_loan_amount'] > 0
|
||||||
|
? ($report['collected_loan_amount'] / $report['collectable_loan_amount']) * 100 : 0;
|
||||||
|
$recurringPercentDone = $report['collectable_recurring_amount'] > 0
|
||||||
|
? ($report['collected_recurring_amount'] / $report['collectable_recurring_amount']) * 100 : 0;
|
||||||
|
?>
|
||||||
|
<div class="report-card">
|
||||||
|
<div class="report-date">
|
||||||
|
<?= date("d M Y", strtotime($report['date'])) ?>
|
||||||
|
</div>
|
||||||
|
<div class="report-details">
|
||||||
|
<p><strong>Loan Target:</strong> ₹ <?= number_format($report['collectable_loan_amount'], 2) ?></p>
|
||||||
|
<p><strong>Loan Collected:</strong> ₹ <?= number_format($report['collected_loan_amount'], 2) ?></p>
|
||||||
|
<p><strong>Recurring Target:</strong> ₹ <?= number_format($report['collectable_recurring_amount'], 2) ?></p>
|
||||||
|
<p><strong>Recurring Collected:</strong> ₹ <?= number_format($report['collected_recurring_amount'], 2) ?></p>
|
||||||
|
</div>
|
||||||
|
<div class="report-progress">
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" style="width: <?= $loanPercentDone ?>%; background: #e95420;"></div>
|
||||||
|
</div>
|
||||||
|
<small>Loan: <?= round($loanPercentDone, 2) ?>% Completed</small>
|
||||||
|
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" style="width: <?= $recurringPercentDone ?>%; background: #007bff;"></div>
|
||||||
|
</div>
|
||||||
|
<small>Recurring: <?= round($recurringPercentDone, 2) ?>% Completed</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="android-links">
|
||||||
|
<a href="/Agent/commission">Commission</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
.welcome-text {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
.success-msg {
|
||||||
|
color: green;
|
||||||
|
background: #e6ffe6;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
.error-msg {
|
||||||
|
color: red;
|
||||||
|
background: #ffe6e6;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
.dashboard-total-section {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.card-box {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 200px;
|
||||||
|
background: linear-gradient(135deg, #f0f0f0ff, #d3d3d3ff);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 6px 20px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
.card-box.highlight {
|
||||||
|
background: linear-gradient(135deg, #e95420, #f37249);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 10px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
transition: width 0.4s ease;
|
||||||
|
}
|
||||||
|
.remaining-text {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #333;
|
||||||
|
background: #f0f0f0;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report Section - Scroll Snap Slider */
|
||||||
|
.report-section {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
.report-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.report-cards {
|
||||||
|
display: flex;
|
||||||
|
overflow-x: auto;
|
||||||
|
scroll-snap-type: x mandatory;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.report-card {
|
||||||
|
flex: 0 0 85%;
|
||||||
|
scroll-snap-align: center;
|
||||||
|
background: linear-gradient(135deg, #ecececff, #ffffffff);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
.report-date {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.report-details p {
|
||||||
|
margin: 4px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
.report-progress {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
.report-card .progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 8px;
|
||||||
|
background: #eee;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 8px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.report-card .progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, #e95420, #f37249);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
/* Report-cards horizontal scrollbar */
|
||||||
|
.report-cards {
|
||||||
|
scrollbar-width: thin; /* Firefox */
|
||||||
|
scrollbar-color: #f37249 rgba(0,0,0,0.04); /* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- WebKit browsers (Chrome, Edge, Safari) --- */
|
||||||
|
.report-cards::-webkit-scrollbar {
|
||||||
|
height: 8px; /* thin horizontal scrollbar */
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-cards::-webkit-scrollbar-track {
|
||||||
|
background: rgba(0,0,0,0.08);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-cards::-webkit-scrollbar-thumb {
|
||||||
|
background: linear-gradient(90deg, #e95420, #f37249);
|
||||||
|
border-radius: 999px; /* ✅ fully rounded pill shape */
|
||||||
|
min-width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover effect */
|
||||||
|
.report-cards::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: linear-gradient(90deg, #d7461c, #e65f3c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.android-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px; /* বাটনের মাঝে ফাঁকা */
|
||||||
|
flex-wrap: wrap; /* ছোট স্ক্রিনে ভাঙবে */
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.android-links a {
|
||||||
|
background: #e95420; /* বাটনের ব্যাকগ্রাউন্ড */
|
||||||
|
color: #fff; /* টেক্সট কালার */
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 25px; /* গোলাকার প্রান্ত */
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: 0 3px 8px rgba(0,0,0,0.2);
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.android-links a:hover {
|
||||||
|
background: #cf471c; /* hover হলে একটু গাঢ় */
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 12px rgba(0,0,0,0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user