first commit
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
const resource = typeof GetParentResourceName === 'function'
|
||||
? GetParentResourceName()
|
||||
: 'devx_banking';
|
||||
const app = document.querySelector('#app');
|
||||
const form = document.querySelector('#transferForm');
|
||||
const transactions = document.querySelector('#transactions');
|
||||
const errorEl = document.querySelector('#error');
|
||||
const format = new Intl.NumberFormat('de-DE');
|
||||
|
||||
async function post(event, data = {}) {
|
||||
const response = await fetch(`https://${resource}/${event}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json; charset=UTF-8' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
function showError(text = '') {
|
||||
errorEl.textContent = text;
|
||||
errorEl.classList.toggle('hidden', !text);
|
||||
}
|
||||
|
||||
function render(overview) {
|
||||
const account = overview.account;
|
||||
document.querySelector('#accountName').textContent = account.accountName;
|
||||
document.querySelector('#accountNumber').textContent = account.accountNumber;
|
||||
document.querySelector('#balance').textContent = `${format.format(account.balance)} $`;
|
||||
|
||||
transactions.innerHTML = '';
|
||||
for (const entry of overview.transactions || []) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'transaction';
|
||||
const sign = entry.direction === 'credit' ? '+' : '−';
|
||||
row.innerHTML = `
|
||||
<div><strong>${escapeHtml(entry.reference)}</strong><br>
|
||||
<small>${escapeHtml(entry.counterparty || '')} · ${escapeHtml(String(entry.createdAt))}</small></div>
|
||||
<strong class="${entry.direction}">${sign}${format.format(entry.amount)} $</strong>`;
|
||||
transactions.appendChild(row);
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value).replace(/[&<>"']/g, char => ({
|
||||
'&': '&', '<': '<', '>': '>', '"': '"', "'": '''
|
||||
}[char]));
|
||||
}
|
||||
|
||||
document.querySelector('#close').addEventListener('click', () => post('close'));
|
||||
document.addEventListener('keyup', event => {
|
||||
if (event.key === 'Escape') post('close');
|
||||
});
|
||||
|
||||
form.addEventListener('submit', async event => {
|
||||
event.preventDefault();
|
||||
showError('');
|
||||
const result = await post('transfer', Object.fromEntries(new FormData(form)));
|
||||
if (!result.ok) {
|
||||
showError(result.error || 'Überweisung fehlgeschlagen.');
|
||||
return;
|
||||
}
|
||||
form.reset();
|
||||
const refreshed = await post('refresh');
|
||||
if (refreshed.ok) render(refreshed.overview);
|
||||
});
|
||||
|
||||
window.addEventListener('message', event => {
|
||||
const data = event.data;
|
||||
if (data.action === 'open') app.classList.remove('hidden');
|
||||
if (data.action === 'close') app.classList.add('hidden');
|
||||
if (data.action === 'overview') render(data.overview);
|
||||
if (data.action === 'error') showError(data.message);
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main id="app" class="hidden">
|
||||
<section class="bank">
|
||||
<header>
|
||||
<div>
|
||||
<p>LOS SANTOS FINANCIAL</p>
|
||||
<h1>Banking</h1>
|
||||
</div>
|
||||
<button id="close" aria-label="Schließen">×</button>
|
||||
</header>
|
||||
|
||||
<div id="error" class="error hidden"></div>
|
||||
|
||||
<section class="account">
|
||||
<div><span>KONTO</span><strong id="accountName">–</strong></div>
|
||||
<div><span>KONTONUMMER</span><strong id="accountNumber">–</strong></div>
|
||||
<div class="balance"><span>VERFÜGBAR</span><strong id="balance">0 $</strong></div>
|
||||
</section>
|
||||
|
||||
<section class="columns">
|
||||
<form id="transferForm">
|
||||
<h2>Überweisung</h2>
|
||||
<label>Empfängerkonto<input name="destination" placeholder="LS0000000000" required></label>
|
||||
<label>Betrag<input name="amount" type="number" min="1" step="1" required></label>
|
||||
<label>Verwendungszweck<input name="reference" maxlength="140" value="Überweisung"></label>
|
||||
<button type="submit">Überweisen</button>
|
||||
</form>
|
||||
|
||||
<div>
|
||||
<h2>Letzte Buchungen</h2>
|
||||
<div id="transactions" class="transactions"></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,47 @@
|
||||
:root { font-family: Inter, Arial, sans-serif; color: #f7f8fb; }
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; overflow: hidden; background: transparent; }
|
||||
.hidden { display: none !important; }
|
||||
#app {
|
||||
min-height: 100vh; display: grid; place-items: center;
|
||||
background: rgba(2,5,9,.55); backdrop-filter: blur(5px);
|
||||
}
|
||||
.bank {
|
||||
width: min(980px, 92vw); max-height: 86vh; overflow: auto;
|
||||
background: #10151e; border: 1px solid rgba(255,255,255,.1);
|
||||
border-radius: 22px; padding: 28px; box-shadow: 0 30px 100px rgba(0,0,0,.55);
|
||||
}
|
||||
header { display: flex; justify-content: space-between; align-items: flex-start; }
|
||||
header p, .account span { color: #8f9aae; font-size: 11px; letter-spacing: .15em; }
|
||||
h1 { margin: 4px 0 22px; font-size: 38px; }
|
||||
h2 { font-size: 18px; }
|
||||
#close { background: transparent; color: white; border: 0; font-size: 32px; cursor: pointer; }
|
||||
.account {
|
||||
display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px;
|
||||
background: linear-gradient(135deg, #2857dd, #1e3e98);
|
||||
border-radius: 16px; padding: 20px;
|
||||
}
|
||||
.account div { display: grid; gap: 7px; }
|
||||
.account .balance strong { font-size: 28px; }
|
||||
.columns { display: grid; grid-template-columns: .8fr 1.2fr; gap: 24px; margin-top: 22px; }
|
||||
form { display: grid; gap: 12px; align-content: start; }
|
||||
label { display: grid; gap: 6px; color: #aeb7c7; font-size: 13px; }
|
||||
input {
|
||||
border: 1px solid rgba(255,255,255,.11); background: #0a0e15;
|
||||
color: white; border-radius: 10px; padding: 12px;
|
||||
}
|
||||
button[type=submit] {
|
||||
border: 0; background: #416cf5; color: white; font-weight: 800;
|
||||
border-radius: 10px; padding: 12px; cursor: pointer;
|
||||
}
|
||||
.transaction {
|
||||
display: grid; grid-template-columns: 1fr auto; gap: 6px;
|
||||
padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,.08);
|
||||
}
|
||||
.transaction small { color: #8f9aae; }
|
||||
.credit { color: #6ee7a5; }
|
||||
.debit { color: #ff8592; }
|
||||
.error { background: rgba(180,45,65,.28); padding: 12px; border-radius: 10px; margin-bottom: 14px; }
|
||||
@media (max-width: 760px) {
|
||||
.account, .columns { grid-template-columns: 1fr; }
|
||||
}
|
||||
Reference in New Issue
Block a user