This commit is contained in:
Ricardo (XenGi) Band 2025-08-17 15:20:50 +02:00
commit dd5d008e7a
No known key found for this signature in database
3 changed files with 154 additions and 24 deletions

View file

@ -6,19 +6,19 @@ In an effort to reduce the usage of Paypal, I created this simple web app. It ca
# How to use
Simple visit the webpage under [BezahlBrudi.jetzt](https://bezahlbrudi.jetzt), and put in your details. The QR code will be generated automatically. You can choose to save your details in your browsers local storage, so you don't have to input your bank details every time.
Simple visit the webpage under [BezahlBrudi.jetzt](https://bezahlbrudi.jetzt), and put in your details. The QR code will be generated automatically as you type. You can choose to save your details in your browsers local storage, so you don't have to input your bank details every time.
# Installation
BezahlBrudi is a PWA that can be installed on your phone. It is a little different depending on the Browser and your OS.
BezahlBrudi is a Progressive Web Application (PWA) that can be installed on your phone. It is a little different depending on the Browser and your OS.
| OS | Browser | Home Screen Shortcut | App Launcher | How to install |
| ------- | -------- | -------------------- | ------------ | -------------- |
| Android | Chrome | ✅ | ✅ | Tap the `Install as App` button or under the `⋮` menu, `Install app` |
| Android | Vanadium | ✅ | ❌ | Under the `⋮` menu, `Install app` |
| Android | Firefox | ✅ | ❌ | Under the `⋮` menu, `Add app to Home screen` |
| iOS | Safari | ✅ | ✅ | Under the `Share` menu, `Add to Home Screen` |
| iOS | Firefox | ❓️ | ❓️ | I don't have an iPhone, please tell me how that works |
| Android | Chrome | ✅ | ✅ | Tap the <kbd>Install as App</kbd> button or under the <kbd>&#x22EE;</kbd> menu, press <kbd>Install app</kbd> |
| Android | Vanadium | ✅ | ❌ | Under the <kbd>&#x22EE;</kbd> menu, press <kbd>Install app</kbd> |
| Android | Firefox | ✅ | ❌ | Under the <kbd>&#x22EE;</kbd> menu, press <kbd>Add app to Home screen</kbd> |
| iOS | Safari | ✅ | ✅ | Under the <kbd>Share</kbd> menu, press <kbd>Add to Home Screen</kbd> |
| iOS | Firefox | ✅ | ✅ | Under the <kbd>&#x2261;</kbd> menu, press <kbd>Share</kbd>, then <kbd>Add to Home screen</kbd> |
# Data privacy
@ -56,6 +56,3 @@ a-zA-Z0-9/?:\(\).,'\+-[:space:]
---
Build with ❤️ and 🍝.
*[PWA]: Progressive Web Application
*[OS]: Operating System

View file

@ -60,11 +60,33 @@
<script src="js/qr-creator.min.js"></script>
</head>
<body>
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a role="button" class="navbar-burger" data-target="navMenu" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a><!--/.navbar-burger-->
</div><!--/.navbar-brand-->
<div class="navbar-menu" id="navMenu">
<div class="navbar-end">
<div class="navbar-item has-dropdown" id="language-dropdown">
<a class="navbar-link" id="current-language">&#x1F1EC;&#x1F1E7; EN</a>
<div class="navbar-dropdown" id="language-selector">
<!-- language items filled from js -->
</div><!--/.navbar-dropdown-->
</div><!--/.navbar-item .has-dropdown .is-hoverable-->
</div><!--/.navbar-end-->
</div><!--/.navbar-menu-->
</nav><!--/.navbar-->
<section class="section">
<div class="container">
<h1 class="title">&#x1F9B8; BezahlBrudi</h1>
<p class="subtitle">Transfer money without any 3rd parties</p>
<p>The QR code can be scanned by most banking apps. Give it a try!</p>
<p class="subtitle" data-i18n="subtitle"></p>
<p data-i18n="explain"></p>
</div>
</section>
@ -73,7 +95,7 @@
<div class="columns">
<div class="column">
<div id="name" class="field">
<label for="input-name" class="label">Receiver Name</label>
<label for="input-name" class="label" data-i18n="name"></label>
<div class="control has-icons-right">
<input id="input-name" class="input" type="text" placeholder="Receiver Name" value="" maxlength="70" required>
<span class="icon is-small is-right"></span>
@ -81,7 +103,7 @@
</div>
<div id="iban" class="field">
<label for="input-iban" class="label">Receiver IBAN</label>
<label for="input-iban" class="label" data-i18n="iban"></label>
<div class="control has-icons-right">
<input id="input-iban" class="input" type="text" value="" required>
<span class="icon is-small is-right"></span>
@ -89,16 +111,16 @@
</div>
<div id="bic" class="field">
<label for="input-bic" class="label">Receiver BIC</label>
<label for="input-bic" class="label" data-i18n="bic"></label>
<div class="control has-icons-right">
<input id="input-bic" class="input" type="text" value="">
<span class="icon is-small is-right"></span>
</div>
<p class="help">Only needed if the Sender and/or Receiver IBAN is outside the EU</p>
<p class="help" data-i18n="bic-help"></p>
</div>
<div id="amount" class="field">
<label for="input-amount" class="label">Amount</label>
<label for="input-amount" class="label" data-i18n="amount"></label>
<div class="control has-icons-left has-icons-right">
<input id="input-amount" class="input" type="number" min="0.00" step="0.01" value="0.00" pattern="[0-9]+.[0-9]{2}" placeholder="0.00" required>
<span class="icon is-small is-left"><b>&euro;</b></span>
@ -107,7 +129,7 @@
</div>
<div id="purpose" class="field">
<label for="input-purpose" class="label">Purpose</label>
<label for="input-purpose" class="label" data-i18n="purpose"></label>
<div class="control has-icons-right">
<input id="input-purpose" class="input" type="text" placeholder="Pizza night!" value="" maxlength="140" required>
<span class="icon is-small is-right"></span>
@ -117,7 +139,7 @@
<div class="field">
<label class="checkbox">
<input id="rememberme" type="checkbox" />
Remember me
<span data-i18n="remember"></span>
</label>
</div>
</div>
@ -134,14 +156,63 @@
<footer class="footer">
<div class="content has-text-centered">
<p>
<strong>BezahlBrudi v1.1.0</strong> by <a href="https://xengi.de">XenGi</a>.
The source code is licensed <a href="https://opensource.org/license/mit">MIT</a>. Find the source code on <a href="https://gitlab.com/xengi/bezahlbrudi/">GitLab</a>.
<br/>
This site doesn't store any data outside your browser, not even cookies. The "Remember me" function stores your data in your browsers local storage. This site doesn't provide any financial services. It is a simple QR code generator.
<strong>BezahlBrudi v1.2.0</strong> by <a href="https://xengi.de">XenGi</a>.
<span data-i18n="disclaimer">
The source code is licensed under <a href="https://opensource.org/license/mit">MIT</a>, you can find it <a href="https://gitlab.com/xengi/bezahlbrudi/">here</a>.
<br/>
This site doesn't store any data outside your browser, not even cookies. The "Remember data" function stores your data in your browsers local storage. This site doesn't provide any financial services. It is a simple QR code generator.</span>
</p>
</div>
</footer>
<script type="application/json" id="i18n-data">
{
"_flags": {
"en": "&#x1F1EC;&#x1F1E7;",
"de": "&#x1F1E9;&#x1F1EA;"
},
"subtitle": {
"en": "Transfer money without any 3rd parties",
"de": "Geld überweisen ohne Drittanbieter"
},
"explain": {
"en": "Simply fill in your details and scan the QR code with your banking app. Give it a try!",
"de": "Trag deine Daten ein und scanne den QR Code einfach mit deiner Banking-App. Probier es aus!"
},
"name": {
"en": "Receiver Name",
"de": "Empfänger Name"
},
"iban": {
"en": "Receiver IBAN",
"de": "Empfänger IBAN"
},
"bic": {
"en": "Receiver BIC",
"de": "Empfänger BIC"
},
"bic-help": {
"en": "Only needed if the Sender or Receiver IBAN is outside the EU",
"de": "Nur nötig wenn Sender oder Empfänger IBAN außerhalb der EU ist"
},
"amount": {
"en": "Amount",
"de": "Betrag"
},
"purpose": {
"en": "Purpose",
"de": "Verwendungszweck"
},
"remember": {
"en": "Remember data",
"de": "Daten merken"
},
"disclaimer": {
"en": "The source code is licensed under <a href=\"https://opensource.org/license/mit\">MIT</a>, you can find it <a href=\"https://gitlab.com/xengi/bezahlbrudi/\">here</a>.<br/>This site doesn't store any data outside your browser, not even cookies. The \"Remember data\" function stores your data in your browsers local storage.<br/>This site doesn't provide any financial services. It is a simple QR code generator.",
"de": "Der Quellcode ist lizensiert unter <a href=\"https://opensource.org/license/mit\">MIT</a>, du kannst ihn <a href=\"https://gitlab.com/xengi/bezahlbrudi/\">hier</a> finden.<br/>Diese Seite speichert keine Daten außerhalb deines Browsers, noch nicht einmal Cookies. Die \"Daten merken\" Funktion speichert Daten im Local Storage des Browsers.<br/>Diese Seite bietet keine Finanzdienstleistungen an. Sie ist lediglich ein QR Code Generator."
}
}
</script>
<script src="js/index.js"></script>
</body>
</html>

View file

@ -1,10 +1,60 @@
// bulma hamburger menu
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Add a click event on each of them
$navbarBurgers.forEach(el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
});
// language selector
document.getElementById("current-language").addEventListener("click", (e) => {
e.preventDefault();
document.getElementById("language-dropdown").classList.toggle("is-active");
});
const i18n = JSON.parse(document.getElementById("i18n-data").textContent);
const i18nSupported = Object.keys(i18n._flags)
// build language selector
const langSelector = document.getElementById("language-selector")
for (const l of i18nSupported) {
const a = document.createElement("a");
a.classList.add("navbar-item");
a.innerHTML = `${i18n._flags[l]} ${l.toUpperCase()}`;
a.href = "#";
a.addEventListener("click", (e) => {
changeLanguage(e.target.textContent.slice(-2).toLowerCase());
document.getElementById("language-dropdown").classList.remove("is-active");
});
langSelector.appendChild(a);
}
changeLanguage = (l) => {
const lang = i18nSupported.includes(l) ? l : "en";
document.querySelectorAll("[data-i18n]").forEach(el => {
el.innerHTML = i18n[el.dataset.i18n][lang];
});
document.getElementById("current-language").innerHTML = `${i18n._flags[lang]} ${lang.toUpperCase()}`;
console.log(`Switching language to ${lang}`);
};
saveFormData = () => {
localStorage.setItem("bezahlbrudiFormData", JSON.stringify({
name: document.querySelector("#name input").value,
iban: document.querySelector("#iban input").value.toUpperCase(),
bic: document.querySelector("#bic input").value.toUpperCase(),
amount: parseFloat(document.querySelector("#amount input").value).toFixed(2),
purpose: document.querySelector("#purpose input").value
purpose: document.querySelector("#purpose input").value,
lang: document.getElementById("current-language").textContent.slice(-2).toLowerCase()
}));
}
@ -224,6 +274,18 @@ if (savedData) {
document.querySelector("#amount input").value = formData["amount"];
document.querySelector("#purpose input").value = formData["purpose"];
document.querySelector("#rememberme").checked = true;
changeLanguage(formData["lang"]);
} else {
// get browser language
let lang = "en"; // default fallback
for (const l of navigator.languages) {
const base = l.split("-")[0];
if (i18nSupported.includes(base)) {
lang = base;
break;
}
}
changeLanguage(lang);
}
// Validate all fields to set css properties