- name
- apexbank-analytics-dashboard
- description
- Build and customize a web-based digital banking dashboard with HTML, CSS, and JavaScript for financial tracking and analytics
- triggers
- ["how do I customize the ApexBank dashboard","set up a digital banking analytics interface","modify ApexBank account balances and transactions","create financial dashboard with ApexBank","integrate custom data into ApexBank","style and theme the banking dashboard","add new features to ApexBank dashboard","configure mock financial data in ApexBank"]
# ApexBank Analytics Dashboard Skill
> Skill by [ara.so](https://ara.so) — Data Skills collection.
## Overview
ApexBank Analytics Hub is a client-side web application that provides a complete digital banking dashboard interface. Built entirely with HTML, CSS, and JavaScript, it offers account monitoring, transaction analysis, investment tracking, savings goals, and financial visualization without requiring a backend server. The dashboard uses glassmorphism design and runs completely in the browser.
## Installation
Clone the repository and serve locally:
```bash
git clone https://github.com/fhuber82/apexbank-analytics-hub.git
cd apexbank-analytics-hub
```
Serve using Python's built-in HTTP server:
```bash
python -m http.server 8000
```
Or use Node.js with `http-server`:
```bash
npx http-server -p 8000
```
Access at `http://localhost:8000`
For production deployment, upload files to any static hosting service (GitHub Pages, Netlify, Vercel, etc.).
## Project Structure
```
apexbank-analytics-hub/
├── index.html # Main dashboard entry point
├── css/
│ ├── styles.css # Core styling and theme
│ └── glassmorphism.css # Glass effect styling
├── js/
│ ├── app.js # Main application logic
│ ├── charts.js # Chart rendering (Chart.js integration)
│ ├── accounts.js # Account management
│ ├── transactions.js # Transaction handling
│ ├── calculator.js # Mortgage/loan calculators
│ └── data.js # Mock data definitions
└── assets/
└── images/ # UI assets and icons
```
## Configuration
### Customizing Mock Data
Edit `js/data.js` to modify default accounts, balances, and transactions:
```javascript
// js/data.js
const mockData = {
accounts: [
{
id: 'acc_001',
name: 'Primary Checking',
type: 'checking',
balance: 5420.50,
currency: 'USD',
accountNumber: '****1234'
},
{
id: 'acc_002',
name: 'Savings Account',
type: 'savings',
balance: 12350.00,
currency: 'USD',
accountNumber: '****5678'
}
],
transactions: [
{
id: 'txn_001',
accountId: 'acc_001',
date: '2026-08-03',
description: 'Grocery Store',
amount: -85.42,
category: 'groceries',
type: 'debit'
},
{
id: 'txn_002',
accountId: 'acc_001',
date: '2026-08-02',
description: 'Salary Deposit',
amount: 3500.00,
category: 'income',
type: 'credit'
}
],
investments: [
{
id: 'inv_001',
name: 'Tech Growth Fund',
symbol: 'TECHGR',
shares: 50,
purchasePrice: 125.00,
currentPrice: 142.30,
totalValue: 7115.00
}
],
savingsGoals: [
{
id: 'goal_001',
name: 'Emergency Fund',
target: 10000,
current: 6500,
deadline: '2026-12-31'
}
]
};
```
### Theming and Styling
Modify CSS variables in `css/styles.css`:
```css
:root {
/* Primary Colors */
--primary-color: #6366f1;
--secondary-color: #8b5cf6;
--accent-color: #ec4899;
/* Background */
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-card: rgba(30, 41, 59, 0.7);
/* Glass Effect */
--glass-bg: rgba(255, 255, 255, 0.05);
--glass-border: rgba(255, 255, 255, 0.1);
--glass-blur: 10px;
/* Text */
--text-primary: #f8fafc;
--text-secondary: #cbd5e1;
--text-muted: #64748b;
/* Status Colors */
--success: #10b981;
--warning: #f59e0b;
--error: #ef4444;
}
```
## Core Functionality
### Account Management
Add new account functionality in `js/accounts.js`:
```javascript
// js/accounts.js
class AccountManager {
constructor() {
this.accounts = this.loadAccounts();
}
loadAccounts() {
const stored = localStorage.getItem('apexbank_accounts');
return stored ? JSON.parse(stored) : mockData.accounts;
}
saveAccounts() {
localStorage.setItem('apexbank_accounts', JSON.stringify(this.accounts));
}
addAccount(accountData) {
const newAccount = {
id: `acc_${Date.now()}`,
...accountData,
createdAt: new Date().toISOString()
};
this.accounts.push(newAccount);
this.saveAccounts();
return newAccount;
}
getAccountById(id) {
return this.accounts.find(acc => acc.id === id);
}
updateBalance(accountId, amount) {
const account = this.getAccountById(accountId);
if (account) {
account.balance += amount;
this.saveAccounts();
this.renderAccounts();
}
}
getTotalBalance() {
return this.accounts.reduce((sum, acc) => sum + acc.balance, 0);
}
renderAccounts() {
const container = document.getElementById('accounts-container');
container.innerHTML = this.accounts.map(account => `
<div class="account-card glass-card" data-account-id="${account.id}">
<div class="account-header">
<h3>${account.name}</h3>
<span class="account-type">${account.type}</span>
</div>
<div class="account-balance">
<span class="currency">${account.currency}</span>
<span class="amount">${account.balance.toFixed(2)}</span>
</div>
<div class="account-number">${account.accountNumber}</div>
</div>
`).join('');
}
}
const accountManager = new AccountManager();
```
### Transaction Processing
Handle transactions in `js/transactions.js`:
```javascript
// js/transactions.js
class TransactionManager {
constructor(accountManager) {
this.accountManager = accountManager;
this.transactions = this.loadTransactions();
}
loadTransactions() {
const stored = localStorage.getItem('apexbank_transactions');
return stored ? JSON.parse(stored) : mockData.transactions;
}
saveTransactions() {
localStorage.setItem('apexbank_transactions', JSON.stringify(this.transactions));
}
addTransaction(transactionData) {
const transaction = {
id: `txn_${Date.now()}`,
date: new Date().toISOString().split('T')[0],
...transactionData
};
this.transactions.unshift(transaction);
this.accountManager.updateBalance(transaction.accountId, transaction.amount);
this.saveTransactions();
return transaction;
}
getTransactionsByAccount(accountId) {
return this.transactions.filter(txn => txn.accountId === accountId);
}
getTransactionsByDateRange(startDate, endDate) {
return this.transactions.filter(txn => {
const txnDate = new Date(txn.date);
return txnDate >= new Date(startDate) && txnDate <= new Date(endDate);
});
}
getCategoryTotals(type = 'debit') {
const filtered = this.transactions.filter(txn => txn.type === type);
const totals = {};
filtered.forEach(txn => {
if (!totals[txn.category]) {
totals[txn.category] = 0;
}
totals[txn.category] += Math.abs(txn.amount);
});
return totals;
}
renderTransactions(filter = {}) {
let filtered = [...this.transactions];
if (filter.accountId) {
filtered = filtered.filter(txn => txn.accountId === filter.accountId);
}
if (filter.category) {
filtered = filtered.filter(txn => txn.category === filter.category);
}
const container = document.getElementById('transactions-list');
container.innerHTML = filtered.map(txn => `
<div class="transaction-item ${txn.type}">
<div class="transaction-icon">
<i class="icon-${txn.category}"></i>
</div>
<div class="transaction-details">
<div class="transaction-description">${txn.description}</div>
<div class="transaction-date">${txn.date}</div>
</div>
<div class="transaction-amount ${txn.amount > 0 ? 'positive' : 'negative'}">
${txn.amount > 0 ? '+' : ''}${txn.amount.toFixed(2)}
</div>
</div>
`).join('');
}
}
const transactionManager = new TransactionManager(accountManager);
```
### Chart Visualization
Integrate Chart.js for analytics in `js/charts.js`:
```javascript
// js/charts.js
class ChartManager {
constructor(transactionManager) {
this.transactionManager = transactionManager;
this.charts = {};
}
renderSpendingChart() {
const ctx = document.getElementById('spending-chart').getContext('2d');
const categoryTotals = this.transactionManager.getCategoryTotals('debit');
if (this.charts.spending) {
this.charts.spending.destroy();
}
this.charts.spending = new Chart(ctx, {
type: 'doughnut',
data: {
labels: Object.keys(categoryTotals),
datasets: [{
data: Object.values(categoryTotals),
backgroundColor: [
'#6366f1',
'#8b5cf6',
'#ec4899',
'#f59e0b',
'#10b981',
'#3b82f6'
],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
color: '#cbd5e1',
font: { size: 12 }
}
}
}
}
});
}
renderCashFlowChart(months = 6) {
const ctx = document.getElementById('cashflow-chart').getContext('2d');
const monthlyData = this.getMonthlyData(months);
if (this.charts.cashflow) {
this.charts.cashflow.destroy();
}
this.charts.cashflow = new Chart(ctx, {
type: 'line',
data: {
labels: monthlyData.labels,
datasets: [
{
label: 'Income',
data: monthlyData.income,
borderColor: '#10b981',
backgroundColor: 'rgba(16, 185, 129, 0.1)',
tension: 0.4
},
{
label: 'Expenses',
data: monthlyData.expenses,
borderColor: '#ef4444',
backgroundColor: 'rgba(239, 68, 68, 0.1)',
tension: 0.4
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
ticks: { color: '#cbd5e1' },
grid: { color: 'rgba(255, 255, 255, 0.1)' }
},
x: {
ticks: { color: '#cbd5e1' },
grid: { color: 'rgba(255, 255, 255, 0.1)' }
}
},
plugins: {
legend: {
labels: { color: '#cbd5e1' }
}
}
}
});
}
getMonthlyData(months) {
const data = { labels: [], income: [], expenses: [] };
const now = new Date();
for (let i = months - 1; i >= 0; i--) {
const month = new Date(now.getFullYear(), now.getMonth() - i, 1);
const monthKey = month.toLocaleDateString('en-US', { month: 'short' });
Voir sur GitHub