Initial commit - Basic bank transactions dashboard structure with Astro and TypeScript

This commit is contained in:
Peter Wood
2025-04-23 20:57:42 -04:00
parent b2dae7e868
commit 0060013561
19 changed files with 767 additions and 16 deletions

View File

@@ -1,16 +1,108 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Sidebar from '../components/Sidebar.astro';
import MainContent from '../components/MainContent.astro';
import type { Account, Transaction } from '../types';
import { formatCurrency, formatDate } from '../utils';
// Initialize with empty arrays until API integration
const accounts: Account[] = [];
const allTransactions: Transaction[] = [];
// Create an empty initial account
const initialAccount: Account = {
id: '',
name: 'No accounts available',
last4: '0000',
balance: 0
};
const initialTransactions: Transaction[] = [];
---
<BaseLayout title="Bank Transactions Dashboard">
<div class="dashboard-layout">
<Sidebar accounts={accounts} initialAccount={initialAccount} />
<MainContent account={initialAccount} transactions={initialTransactions} />
</div>
</BaseLayout>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
</body>
</html>
<script define:vars={{ allAccounts: accounts, allTransactions }}>
// Client-side script to handle account switching and updating the UI
// --- DOM Elements ---
const accountSelect = document.getElementById('account-select');
const currentAccountNameSpan = document.getElementById('current-account-name');
const accountBalanceSpan = document.getElementById('account-balance');
const transactionTableBody = document.getElementById('transaction-table-body');
// --- Helper Functions (mirror utils.ts for client-side use) ---
function formatCurrency(amount) {
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount);
}
function formatDate(dateString) {
const date = new Date(dateString + 'T00:00:00'); // Ensure local date
return new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'short', day: 'numeric' }).format(date);
}
// --- Update UI Function ---
function updateUIForAccount(accountId) {
console.log("Updating UI for account:", accountId); // Debug log
const selectedAccount = allAccounts.find(acc => acc.id === accountId);
const accountTransactions = allTransactions
.filter(txn => txn.accountId === accountId)
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); // Sort desc
if (!selectedAccount || !transactionTableBody || !currentAccountNameSpan || !accountBalanceSpan) {
console.error("Required UI elements not found!");
return;
}
// Update header
currentAccountNameSpan.textContent = `${selectedAccount.name} (***${selectedAccount.last4})`;
// Update summary
accountBalanceSpan.textContent = formatCurrency(selectedAccount.balance);
// Update table
transactionTableBody.innerHTML = ''; // Clear existing rows
if (accountTransactions.length === 0) {
transactionTableBody.innerHTML = `<tr><td colspan="4" style="text-align: center; font-style: italic; color: #777;">No transactions found for this account.</td></tr>`;
} else {
accountTransactions.forEach(txn => {
const row = document.createElement('tr');
row.setAttribute('data-txn-id', txn.id);
row.innerHTML = `
<td>${formatDate(txn.date)}</td>
<td>${txn.description}</td>
<td class="amount-col ${txn.amount >= 0 ? 'amount-positive' : 'amount-negative'}">
${formatCurrency(txn.amount)}
</td>
<td>
<button class="action-btn edit-btn" title="Edit transaction (not implemented)">Edit</button>
<button class="action-btn delete-btn" title="Delete transaction (not implemented)">Delete</button>
</td>
`;
transactionTableBody.appendChild(row);
});
}
}
// --- Event Listener ---
if (accountSelect) {
accountSelect.addEventListener('change', (event) => {
const selectedAccountId = event.target.value;
updateUIForAccount(selectedAccountId);
});
} else {
console.error("Account select element not found");
}
// --- Initial Load (Optional but good practice) ---
// The page already renders the initial state server-side,
// so no need to call updateUIForAccount() immediately unless
// there's a chance the JS loads before initial render completes fully.
// console.log("Account switcher script loaded.");
</script>