Jacob Schmidt 603963c935 Refactor bank UI to bridge-driven single-page flow
- Replace separate bank/ATM pages with a unified `index.html` app bundle
- Split bank init into `initClass`, `initSessionService`, and `initUIBridge`
- Route UI events through `BankUIBridge` and refresh session payloads after sync
2026-03-14 12:11:34 -05:00

344 lines
9.0 KiB
JavaScript

(function () {
const BankApp = (window.BankApp = window.BankApp || {});
const store = BankApp.store;
let noticeTimer = null;
function getAccount() {
return BankApp.data?.account || {};
}
function getSession() {
return BankApp.data?.session || {};
}
function normalizeAmount(value) {
const amount = Math.floor(Number(value || 0));
return Number.isFinite(amount) ? amount : 0;
}
function showNotice(type, text) {
store.setNotice({ type, text });
if (noticeTimer) {
clearTimeout(noticeTimer);
}
noticeTimer = setTimeout(() => {
store.setNotice({ text: "", type: "" });
noticeTimer = null;
}, 3200);
}
function closeBank() {
const bridge = BankApp.bridge;
if (bridge && typeof bridge.requestClose === "function") {
const sent = bridge.requestClose();
if (sent) {
return true;
}
}
showNotice("error", "Bank bridge is unavailable.");
return false;
}
function refreshBank() {
const bridge = BankApp.bridge;
if (bridge && typeof bridge.requestRefresh === "function") {
const sent = bridge.requestRefresh();
if (sent) {
return true;
}
}
showNotice("error", "Bank refresh bridge is unavailable.");
return false;
}
function requestDeposit(amountValue) {
const amount = normalizeAmount(amountValue);
const account = getAccount();
if (amount <= 0) {
showNotice("error", "Enter a valid deposit amount.");
return false;
}
if (amount > Number(account.cash || 0)) {
showNotice("error", "Cash on hand cannot cover that deposit.");
return false;
}
const bridge = BankApp.bridge;
if (!bridge || typeof bridge.requestDeposit !== "function") {
showNotice("error", "Deposit bridge is unavailable.");
return false;
}
store.startAction("deposit");
const sent = bridge.requestDeposit({ amount });
if (!sent) {
store.finishAction();
showNotice("error", "Deposit bridge is unavailable.");
return false;
}
return true;
}
function requestWithdraw(amountValue) {
const amount = normalizeAmount(amountValue);
const account = getAccount();
if (amount <= 0) {
showNotice("error", "Enter a valid withdrawal amount.");
return false;
}
if (amount > Number(account.bank || 0)) {
showNotice("error", "Bank balance cannot cover that withdrawal.");
return false;
}
const bridge = BankApp.bridge;
if (!bridge || typeof bridge.requestWithdraw !== "function") {
showNotice("error", "Withdraw bridge is unavailable.");
return false;
}
store.startAction("withdraw");
const sent = bridge.requestWithdraw({ amount });
if (!sent) {
store.finishAction();
showNotice("error", "Withdraw bridge is unavailable.");
return false;
}
return true;
}
function requestTransfer(targetUid, amountValue) {
const amount = normalizeAmount(amountValue);
const session = getSession();
const account = getAccount();
const targetId = String(targetUid || "").trim();
if (!targetId) {
showNotice("error", "Select a transfer recipient.");
return false;
}
if (targetId === String(session.uid || "")) {
showNotice("error", "You cannot transfer funds to yourself.");
return false;
}
if (amount <= 0) {
showNotice("error", "Enter a valid transfer amount.");
return false;
}
if (amount > Number(account.bank || 0)) {
showNotice("error", "Bank balance cannot cover that transfer.");
return false;
}
const bridge = BankApp.bridge;
if (!bridge || typeof bridge.requestTransfer !== "function") {
showNotice("error", "Transfer bridge is unavailable.");
return false;
}
store.startAction("transfer");
const sent = bridge.requestTransfer({
amount,
from: "bank",
target: targetId,
});
if (!sent) {
store.finishAction();
showNotice("error", "Transfer bridge is unavailable.");
return false;
}
return true;
}
function requestDepositEarnings(amountValue) {
const amount = normalizeAmount(amountValue);
const account = getAccount();
if (amount <= 0) {
showNotice("error", "No earnings are available to deposit.");
return false;
}
if (amount > Number(account.earnings || 0)) {
showNotice(
"error",
"Pending earnings cannot cover that deposit request.",
);
return false;
}
const bridge = BankApp.bridge;
if (!bridge || typeof bridge.requestDepositEarnings !== "function") {
showNotice("error", "Earnings bridge is unavailable.");
return false;
}
store.startAction("depositearnings");
const sent = bridge.requestDepositEarnings({ amount });
if (!sent) {
store.finishAction();
showNotice("error", "Earnings bridge is unavailable.");
return false;
}
return true;
}
function appendPinDigit(digit) {
const nextDigit = String(digit || "").trim();
if (!nextDigit) {
return;
}
const currentPin = String(store.getEnteredPin() || "");
if (currentPin.length >= 4) {
return;
}
store.setEnteredPin(currentPin + nextDigit);
}
function backspacePin() {
const currentPin = String(store.getEnteredPin() || "");
store.setEnteredPin(currentPin.slice(0, -1));
}
function clearPin() {
store.setEnteredPin("");
}
function submitPin() {
const enteredPin = String(store.getEnteredPin() || "");
const actualPin = String(getAccount().pin || "1234");
if (enteredPin.length !== 4) {
showNotice("error", "Enter your four-digit access PIN.");
return false;
}
if (enteredPin !== actualPin) {
clearPin();
showNotice("error", "Incorrect PIN.");
return false;
}
clearPin();
store.setAtmView("menu");
return true;
}
function selectAtmView(view) {
const nextView = String(view || "").trim();
if (!nextView) {
return false;
}
if (nextView === "pin") {
store.resetAtm();
return true;
}
store.setCustomAmount("");
store.setAtmView(nextView);
return true;
}
function appendCustomAmountDigit(digit) {
const nextDigit = String(digit || "").trim();
if (!nextDigit) {
return;
}
const currentValue = String(store.getCustomAmount() || "");
if (currentValue.length >= 7) {
return;
}
store.setCustomAmount(currentValue + nextDigit);
}
function backspaceCustomAmount() {
const currentValue = String(store.getCustomAmount() || "");
store.setCustomAmount(currentValue.slice(0, -1));
}
function clearCustomAmount() {
store.setCustomAmount("");
}
function submitCustomAmount(kind) {
const amount = normalizeAmount(store.getCustomAmount());
const nextKind = String(kind || "")
.trim()
.toLowerCase();
if (amount <= 0) {
showNotice("error", "Enter a valid transaction amount.");
return false;
}
const success =
nextKind === "deposit"
? requestDeposit(amount)
: requestWithdraw(amount);
if (success) {
store.setCustomAmount("");
store.setAtmView("menu");
}
return success;
}
function requestAtmAmount(kind, amount) {
const nextKind = String(kind || "")
.trim()
.toLowerCase();
const success =
nextKind === "deposit"
? requestDeposit(amount)
: requestWithdraw(amount);
if (success) {
store.setAtmView("menu");
}
return success;
}
BankApp.actions = {
appendCustomAmountDigit,
appendPinDigit,
backspaceCustomAmount,
backspacePin,
clearCustomAmount,
clearPin,
closeBank,
refreshBank,
requestAtmAmount,
requestDeposit,
requestDepositEarnings,
requestTransfer,
requestWithdraw,
selectAtmView,
showNotice,
submitCustomAmount,
submitPin,
};
})();