mirror of
https://github.com/Solo-Web-Works/BillTrak.git
synced 2026-01-29 08:40:34 +00:00
✨feature: Add YTD summary and update adding and editing for new database schema
This commit is contained in:
@@ -581,6 +581,9 @@
|
|||||||
.mr-auto {
|
.mr-auto {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
.mb-0 {
|
||||||
|
margin-bottom: calc(var(--spacing) * 0);
|
||||||
|
}
|
||||||
.mb-2 {
|
.mb-2 {
|
||||||
margin-bottom: calc(var(--spacing) * 2);
|
margin-bottom: calc(var(--spacing) * 2);
|
||||||
}
|
}
|
||||||
@@ -608,6 +611,9 @@
|
|||||||
.inline {
|
.inline {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
.inline-block {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
.inline-flex {
|
.inline-flex {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
@@ -650,6 +656,12 @@
|
|||||||
.resize {
|
.resize {
|
||||||
resize: both;
|
resize: both;
|
||||||
}
|
}
|
||||||
|
.list-disc {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
.list-none {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
.grid-cols-1 {
|
.grid-cols-1 {
|
||||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
@@ -718,6 +730,9 @@
|
|||||||
.bg-gray-300 {
|
.bg-gray-300 {
|
||||||
background-color: var(--color-gray-300);
|
background-color: var(--color-gray-300);
|
||||||
}
|
}
|
||||||
|
.bg-green-500 {
|
||||||
|
background-color: var(--color-green-500);
|
||||||
|
}
|
||||||
.bg-red-300 {
|
.bg-red-300 {
|
||||||
background-color: var(--color-red-300);
|
background-color: var(--color-red-300);
|
||||||
}
|
}
|
||||||
@@ -757,6 +772,15 @@
|
|||||||
.py-2 {
|
.py-2 {
|
||||||
padding-block: calc(var(--spacing) * 2);
|
padding-block: calc(var(--spacing) * 2);
|
||||||
}
|
}
|
||||||
|
.pb-1 {
|
||||||
|
padding-bottom: calc(var(--spacing) * 1);
|
||||||
|
}
|
||||||
|
.pl-0 {
|
||||||
|
padding-left: calc(var(--spacing) * 0);
|
||||||
|
}
|
||||||
|
.pl-5 {
|
||||||
|
padding-left: calc(var(--spacing) * 5);
|
||||||
|
}
|
||||||
.text-2xl {
|
.text-2xl {
|
||||||
font-size: var(--text-2xl);
|
font-size: var(--text-2xl);
|
||||||
line-height: var(--tw-leading, var(--text-2xl--line-height));
|
line-height: var(--tw-leading, var(--text-2xl--line-height));
|
||||||
@@ -765,6 +789,10 @@
|
|||||||
font-size: var(--text-4xl);
|
font-size: var(--text-4xl);
|
||||||
line-height: var(--tw-leading, var(--text-4xl--line-height));
|
line-height: var(--tw-leading, var(--text-4xl--line-height));
|
||||||
}
|
}
|
||||||
|
.text-lg {
|
||||||
|
font-size: var(--text-lg);
|
||||||
|
line-height: var(--tw-leading, var(--text-lg--line-height));
|
||||||
|
}
|
||||||
.text-sm {
|
.text-sm {
|
||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
line-height: var(--tw-leading, var(--text-sm--line-height));
|
line-height: var(--tw-leading, var(--text-sm--line-height));
|
||||||
@@ -781,6 +809,10 @@
|
|||||||
--tw-font-weight: var(--font-weight-medium);
|
--tw-font-weight: var(--font-weight-medium);
|
||||||
font-weight: var(--font-weight-medium);
|
font-weight: var(--font-weight-medium);
|
||||||
}
|
}
|
||||||
|
.font-semibold {
|
||||||
|
--tw-font-weight: var(--font-weight-semibold);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
}
|
||||||
.text-gray-500 {
|
.text-gray-500 {
|
||||||
color: var(--color-gray-500);
|
color: var(--color-gray-500);
|
||||||
}
|
}
|
||||||
@@ -820,6 +852,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.hover\:bg-green-600 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
background-color: var(--color-green-600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.hover\:bg-red-400 {
|
.hover\:bg-red-400 {
|
||||||
&:hover {
|
&:hover {
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
@@ -849,6 +888,11 @@
|
|||||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.lg\:grid-cols-2 {
|
||||||
|
@media (width >= 64rem) {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
.lg\:grid-cols-4 {
|
.lg\:grid-cols-4 {
|
||||||
@media (width >= 64rem) {
|
@media (width >= 64rem) {
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
|||||||
@@ -18,18 +18,25 @@ try {
|
|||||||
switch($action) {
|
switch($action) {
|
||||||
case 'add':
|
case 'add':
|
||||||
$data = [
|
$data = [
|
||||||
'date' => (new DateTime($_POST['date']))->format('Y-m-d'),
|
'date' => (new DateTime($_POST['date']))->format('Y-m-d'),
|
||||||
'payeeId' => $_POST['payeeId'], // Payee ID instead of name
|
'payeeId' => $_POST['payeeId'], // Payee ID instead of name
|
||||||
'amount' => (float)$_POST['amount'],
|
'amount' => (float)$_POST['amount'],
|
||||||
'paymentId' => $_POST['paymentId'],
|
'paymentId' => $_POST['paymentId'],
|
||||||
'comment' => $_POST['comment'] ?? '',
|
'comment' => $_POST['comment'] ?? '',
|
||||||
'year' => (int)explode('-', $_POST['date'])[0]
|
'year' => (int)explode('-', $_POST['date'])[0]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (empty($data['date']) || empty($data['payeeId']) || $data['amount'] <= 0) {
|
||||||
|
echo json_encode(['error' => 'Missing required fields.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
$stmt = DB::connect()->prepare("
|
$stmt = DB::connect()->prepare("
|
||||||
INSERT INTO bills (billDate, payeeId, amount, paymentId, comment, year)
|
INSERT INTO bills (billDate, payeeId, amount, paymentId, comment, year)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
");
|
");
|
||||||
|
|
||||||
$result = $stmt->execute([
|
$result = $stmt->execute([
|
||||||
$data['date'],
|
$data['date'],
|
||||||
$data['payeeId'],
|
$data['payeeId'],
|
||||||
@@ -49,27 +56,27 @@ try {
|
|||||||
$data = [
|
$data = [
|
||||||
'id' => $_POST['id'],
|
'id' => $_POST['id'],
|
||||||
'date' => (new DateTime($_POST['date']))->format('Y-m-d'),
|
'date' => (new DateTime($_POST['date']))->format('Y-m-d'),
|
||||||
'billName' => $_POST['billName'],
|
'payeeId' => $_POST['payeeId'],
|
||||||
'amount' => (float)$_POST['amount'],
|
'amount' => (float)$_POST['amount'],
|
||||||
'paymentId' => $_POST['paymentId'],
|
'paymentId' => $_POST['paymentId'],
|
||||||
'comment' => $_POST['comment'] ?? ''
|
'comment' => $_POST['comment'] ?? ''
|
||||||
];
|
];
|
||||||
|
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
if (empty($data['id']) || empty($data['date']) || empty($data['billName']) || $data['amount'] <= 0) {
|
if (empty($data['id']) || empty($data['date']) || empty($data['payeeId']) || $data['amount'] <= 0) {
|
||||||
throw new MissingRequiredException('Missing required fields.');
|
throw new MissingRequiredException('Missing required fields.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare and execute the update statement
|
// Prepare and execute the update statement
|
||||||
$stmt = DB::connect()->prepare("
|
$stmt = DB::connect()->prepare("
|
||||||
UPDATE bills
|
UPDATE bills
|
||||||
SET billDate = ?, billName = ?, amount = ?, paymentId = ?, comment = ?
|
SET billDate = ?, payeeId = ?, amount = ?, paymentId = ?, comment = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
");
|
");
|
||||||
|
|
||||||
$result = $stmt->execute([
|
$result = $stmt->execute([
|
||||||
$data['date'],
|
$data['date'],
|
||||||
$data['billName'],
|
$data['payeeId'],
|
||||||
$data['amount'],
|
$data['amount'],
|
||||||
$data['paymentId'],
|
$data['paymentId'],
|
||||||
$data['comment'],
|
$data['comment'],
|
||||||
@@ -93,9 +100,18 @@ try {
|
|||||||
|
|
||||||
case 'getById':
|
case 'getById':
|
||||||
$id = $_GET['id'];
|
$id = $_GET['id'];
|
||||||
$stmt = DB::connect()->prepare("SELECT * FROM bills WHERE id = ?");
|
|
||||||
|
$stmt = DB::connect()->prepare("
|
||||||
|
SELECT bills.*, payees.name AS payeeName, payees.id AS payeeId
|
||||||
|
FROM bills
|
||||||
|
JOIN payees ON bills.payeeId = payees.id
|
||||||
|
WHERE bills.id = ?
|
||||||
|
");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
echo json_encode($stmt->fetch(PDO::FETCH_ASSOC));
|
|
||||||
|
$bill = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo json_encode($bill);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'getTotals':
|
case 'getTotals':
|
||||||
@@ -150,6 +166,37 @@ try {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'getYtdAmounts':
|
||||||
|
$year = $_GET['year'] ?? date('Y');
|
||||||
|
|
||||||
|
// Fetch YTD amounts for each payee
|
||||||
|
$stmt = DB::connect()->prepare("
|
||||||
|
SELECT payees.name AS payeeName, SUM(bills.amount) AS totalAmount
|
||||||
|
FROM bills
|
||||||
|
JOIN payees ON bills.payeeId = payees.id
|
||||||
|
WHERE bills.year = ?
|
||||||
|
GROUP BY payees.name
|
||||||
|
ORDER BY payees.name ASC
|
||||||
|
");
|
||||||
|
$stmt->execute([$year]);
|
||||||
|
$payeeAmounts = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// Fetch overall YTD amount
|
||||||
|
$stmt = DB::connect()->prepare("
|
||||||
|
SELECT SUM(amount) AS overallAmount
|
||||||
|
FROM bills
|
||||||
|
WHERE year = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$year]);
|
||||||
|
|
||||||
|
$overallAmount = $stmt->fetch(PDO::FETCH_ASSOC)['overallAmount'] ?? 0;
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'payeeAmounts' => $payeeAmounts,
|
||||||
|
'overallAmount' => $overallAmount
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidActionException('Invalid action');
|
throw new InvalidActionException('Invalid action');
|
||||||
}
|
}
|
||||||
|
|||||||
36
index.php
36
index.php
@@ -18,13 +18,13 @@
|
|||||||
|
|
||||||
<!-- Add Bill Form -->
|
<!-- Add Bill Form -->
|
||||||
<form id="billForm" class="bg-white p-4 mb-6 rounded shadow">
|
<form id="billForm" class="bg-white p-4 mb-6 rounded shadow">
|
||||||
<h2 class="text-2xl font-bold mb-4">Bill Payments</h2>
|
<h2 class="text-2xl font-bold mb-4">Add New Payment</h2>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
||||||
<input type="date" name="date" required class="p-2 border rounded">
|
<input type="date" name="date" required class="p-2 border rounded">
|
||||||
|
|
||||||
<select required id="billName" name="billName" class="border rounded p-2">
|
<select required id="payeeId" name="payeeId" class="border rounded p-2">
|
||||||
<option value="" disabled selected>Select Payee</option>
|
<!-- Payees will be populated here -->
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<input type="number" step="0.01" name="amount" placeholder="Amount" required class="p-2 border rounded">
|
<input type="number" step="0.01" name="amount" placeholder="Amount" required class="p-2 border rounded">
|
||||||
@@ -46,10 +46,28 @@
|
|||||||
<button type="submit" class="mt-4 bg-blue-500 text-white px-4 py-2 rounded">Add Payee</button>
|
<button type="submit" class="mt-4 bg-blue-500 text-white px-4 py-2 rounded">Add Payee</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- Chart -->
|
<!-- Chart & Totals -->
|
||||||
<div class="border p-4 rounded shadow bg-gray-100">
|
<div class="border p-4 rounded shadow bg-gray-100 grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
<h2 class="text-2xl font-bold mb-4">Chart</h2>
|
<div id="chartSection" class="bg-white p-4 rounded shadow mb-6">
|
||||||
<canvas id="chart"></canvas>
|
<h3 class="text-xl font-bold mb-4">Chart</h3>
|
||||||
|
<canvas id="chart"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="ytdSection" class="bg-white p-4 rounded shadow mb-6">
|
||||||
|
<h3 class="text-xl font-bold mb-4">Year-to-Date Summary</h3>
|
||||||
|
|
||||||
|
<div id="ytdOverall" class="mb-4">
|
||||||
|
<h3 class="text-lg font-semibold mb-0 inline-block">Overall YTD Amount:</h3> <span id="ytdOverallAmount" class="text-lg font-semibold">$0.00</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="ytdPayees">
|
||||||
|
<h3 class="text-lg font-semibold mb-0 inline-block">YTD by Payee:</h3>
|
||||||
|
|
||||||
|
<ul id="ytdPayeeList" class="list-none pl-0">
|
||||||
|
<!-- Payee amounts will be populated here -->
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -100,8 +118,8 @@
|
|||||||
|
|
||||||
<!-- Bill Name -->
|
<!-- Bill Name -->
|
||||||
<div>
|
<div>
|
||||||
<label for="editFormBillName" class="block text-sm font-medium">Payee</label>
|
<label for="editFormPayeeId" class="block text-sm font-medium">Payee</label>
|
||||||
<select id="editFormBillName" name="billName" class="border rounded px-3 py-2 w-full">
|
<select id="editFormPayeeId" name="payeeId" class="border rounded px-3 py-2 w-full">
|
||||||
<option value="" disabled>Select Payee</option>
|
<option value="" disabled>Select Payee</option>
|
||||||
<!-- Options will be populated dynamically -->
|
<!-- Options will be populated dynamically -->
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
87
js/app.js
87
js/app.js
@@ -3,6 +3,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const sortSelect = document.getElementById('sortSelect');
|
const sortSelect = document.getElementById('sortSelect');
|
||||||
const billList = document.getElementById('billList');
|
const billList = document.getElementById('billList');
|
||||||
const form = document.getElementById('billForm');
|
const form = document.getElementById('billForm');
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
// Populate the year dropdown
|
// Populate the year dropdown
|
||||||
async function loadYears() {
|
async function loadYears() {
|
||||||
@@ -27,13 +28,21 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch and display payees
|
// Fetch and display payees
|
||||||
async function loadPayees() {
|
async function loadPayees(selectId) {
|
||||||
const response = await fetch('/includes/api.php?action=getPayees');
|
const response = await fetch('/includes/api.php?action=getPayees');
|
||||||
const payees = await response.json();
|
const payees = await response.json();
|
||||||
|
|
||||||
const payeeSelect = document.getElementById('billName');
|
const payeeSelect = document.getElementById(selectId || 'payeeId');
|
||||||
|
|
||||||
payeeSelect.innerHTML = ''; // Clear existing options
|
payeeSelect.innerHTML = ''; // Clear existing options
|
||||||
|
|
||||||
|
const defaultOption = document.createElement('option');
|
||||||
|
defaultOption.value = '';
|
||||||
|
defaultOption.textContent = 'Select Payee';
|
||||||
|
defaultOption.disabled = true;
|
||||||
|
defaultOption.selected = true;
|
||||||
|
payeeSelect.appendChild(defaultOption);
|
||||||
|
|
||||||
payees.forEach(payee => {
|
payees.forEach(payee => {
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.value = payee.id; // Use payee ID as the value
|
option.value = payee.id; // Use payee ID as the value
|
||||||
@@ -73,7 +82,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
<p><strong>Amount:</strong> $${bill.amount.toFixed(2)}</p>
|
<p><strong>Amount:</strong> $${bill.amount.toFixed(2)}</p>
|
||||||
<p><strong>Payment ID:</strong> ${bill.paymentId || 'N/A'}</p>
|
<p><strong>Payment ID:</strong> ${bill.paymentId || 'N/A'}</p>
|
||||||
<p><strong>Comment:</strong> ${bill.comment || 'N/A'}</p>
|
<p><strong>Comment:</strong> ${bill.comment || 'N/A'}</p>
|
||||||
<button class="block absolute top-2 right-2 border text-gray-500 hover:text-gray-700 px-2 py-0 rounded" data-id="${bill.id}">Edit</button>
|
<button class="block absolute top-2 right-2 px-2 py-0 pb-1 rounded bg-green-500 text-white hover:bg-green-600" data-id="${bill.id}">Edit</button>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
billList.appendChild(billItem);
|
billList.appendChild(billItem);
|
||||||
@@ -99,17 +108,42 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.getElementById('editFormComment').value = bill.comment || '';
|
document.getElementById('editFormComment').value = bill.comment || '';
|
||||||
|
|
||||||
// Populate the payee dropdown and select the correct option
|
// Populate the payee dropdown and select the correct option
|
||||||
await loadPayees(); // Ensure the payee dropdown is populated
|
await loadPayees('editFormPayeeId'); // Ensure the payee dropdown is populated
|
||||||
document.getElementById('editFormBillName').value = bill.billName;
|
|
||||||
|
const payeeDropdown = document.getElementById('editFormPayeeId');
|
||||||
|
payeeDropdown.value = bill.payeeId; // Use payeeId instead of billName
|
||||||
|
|
||||||
// Open the modal
|
// Open the modal
|
||||||
document.getElementById('editModal').classList.add('flex');
|
document.getElementById('editModal').classList.add('flex');
|
||||||
document.getElementById('editModal').classList.remove('hidden');
|
document.getElementById('editModal').classList.remove('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadYtdAmounts(year) {
|
||||||
|
const response = await fetch(`/includes/api.php?action=getYtdAmounts&year=${year}`);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
// Display overall YTD amount
|
||||||
|
const ytdOverallAmount = document.getElementById('ytdOverallAmount');
|
||||||
|
ytdOverallAmount.textContent = `$${(data.overallAmount || 0).toFixed(2)}`;
|
||||||
|
|
||||||
|
// Display YTD amounts by payee
|
||||||
|
const ytdPayeeList = document.getElementById('ytdPayeeList');
|
||||||
|
ytdPayeeList.innerHTML = ''; // Clear existing items
|
||||||
|
|
||||||
|
data.payeeAmounts.forEach(payee => {
|
||||||
|
const listItem = document.createElement('li');
|
||||||
|
const strongElement = document.createElement('strong');
|
||||||
|
strongElement.textContent = `${payee.payeeName}:`;
|
||||||
|
listItem.appendChild(strongElement);
|
||||||
|
listItem.appendChild(document.createTextNode(` $${payee.totalAmount.toFixed(2)}`));
|
||||||
|
ytdPayeeList.appendChild(listItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Add event listener for year selection
|
// Add event listener for year selection
|
||||||
yearSelect.addEventListener('change', (e) => {
|
yearSelect.addEventListener('change', (e) => {
|
||||||
const selectedYear = e.target.value;
|
const selectedYear = e.target.value;
|
||||||
|
loadYtdAmounts(selectedYear);
|
||||||
loadBills(selectedYear, sortSelect.value); // Use the selected sort order
|
loadBills(selectedYear, sortSelect.value); // Use the selected sort order
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -119,6 +153,26 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
loadBills(yearSelect.value, selectedSort); // Use the selected year
|
loadBills(yearSelect.value, selectedSort); // Use the selected year
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add new bill
|
||||||
|
form.addEventListener('submit', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const formData = new FormData(form);
|
||||||
|
|
||||||
|
const response = await fetch('/includes/api.php?action=add', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
form.reset();
|
||||||
|
loadYears(); // Reload years in case a new year was added
|
||||||
|
loadYtdAmounts(yearSelect.value); // Reload YTD amounts
|
||||||
|
} else {
|
||||||
|
alert('Failed to add bill. Please try again.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Add new payee
|
// Add new payee
|
||||||
document.getElementById('addPayeeForm').addEventListener('submit', async (e) => {
|
document.getElementById('addPayeeForm').addEventListener('submit', async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -130,31 +184,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
loadPayees(); // Reload payee dropdown
|
loadPayees('payeeId'); // Reload payee dropdown
|
||||||
e.target.reset(); // Clear the form
|
e.target.reset(); // Clear the form
|
||||||
} else {
|
} else {
|
||||||
alert('Failed to add payee. Please try again.');
|
alert('Failed to add payee. Please try again.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add new bill
|
|
||||||
form.addEventListener('submit', async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const formData = new FormData(form);
|
|
||||||
const response = await fetch('/includes/api.php?action=add', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
form.reset();
|
|
||||||
loadYears(); // Reload years in case a new year was added
|
|
||||||
} else {
|
|
||||||
alert('Failed to add bill. Please try again.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Event listener for edit buttons within bill items
|
// Event listener for edit buttons within bill items
|
||||||
billList.addEventListener('click', (e) => {
|
billList.addEventListener('click', (e) => {
|
||||||
if (e.target.tagName === 'BUTTON' && e.target.textContent === 'Edit') {
|
if (e.target.tagName === 'BUTTON' && e.target.textContent === 'Edit') {
|
||||||
@@ -193,6 +229,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// On page load
|
// On page load
|
||||||
|
loadPayees('payeeId');
|
||||||
loadYears();
|
loadYears();
|
||||||
loadPayees();
|
loadYtdAmounts(currentYear);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user