pesaqr
Version:
QR Code Banner to scan and pay M-PESA for any Till/Paybill Number via the M-PESA app
189 lines (182 loc) • 6.22 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { LitElement, html, css } from "lit";
import { customElement, property } from "lit/decorators.js";
import qrcode from "qrcode-generator";
const TRANSACTION_TYPE = {
TILL_NUMBER: "till",
PAYBILL: "paybill",
SEND_MONEY: "phone",
};
let PesaQR = class PesaQR extends LitElement {
constructor() {
super();
this.type = "till";
this.tillNumber = "";
this.paybillNumber = "";
this.accountNumber = "";
this.phoneNumber = "";
this.amount = "";
this.width = null;
this.theme = "light";
this.loading = false;
this.error = null;
this.type = "till";
this.tillNumber = "";
this.paybillNumber = "";
this.accountNumber = "";
this.phoneNumber = "";
this.amount = "";
this.width = null;
}
render() {
return html `
<div class="pesaqr">
<div class="qr-header">SCAN WITH M-PESA</div>
<div id="qrcode"></div>
</div>
`;
}
updated(changedProperties) {
if (changedProperties.has("type") ||
changedProperties.has("tillNumber") ||
changedProperties.has("paybillNumber") ||
changedProperties.has("accountNumber") ||
changedProperties.has("phoneNumber") ||
changedProperties.has("amount")) {
this.generateQRCode();
}
if (changedProperties.has("width")) {
if (this.width) {
this.style.setProperty("--qr-width", `${this.width}px`);
}
}
}
generateQRCode() {
let qrData = "";
switch (this.type) {
case TRANSACTION_TYPE.TILL_NUMBER:
if (this.tillNumber) {
qrData = `BG|${this.tillNumber}|${this.amount}`;
}
break;
case TRANSACTION_TYPE.PAYBILL:
if (this.paybillNumber && this.accountNumber) {
qrData = `PB|${this.paybillNumber}|${this.amount}|${this.accountNumber}`;
}
break;
case TRANSACTION_TYPE.SEND_MONEY:
if (this.phoneNumber) {
qrData = `SM|${this.phoneNumber}|${this.amount}`;
}
break;
default:
console.error("Invalid transaction type");
return;
}
if (qrData) {
const qr = qrcode(0, "L");
qr.addData(qrData);
qr.make();
const qrCodeContainer = this.shadowRoot?.getElementById("qrcode");
if (qrCodeContainer) {
qrCodeContainer.innerHTML = qr.createImgTag(20);
}
}
}
};
PesaQR.styles = css `
:host {
display: block;
font-family: Arial, sans-serif;
--qr-size: calc(var(--qr-width, 600px) * 0.35);
--header-padding: calc(var(--qr-size) * 0.025);
--border-radius: calc(var(--qr-size) * 0.05);
--font-size: calc(var(--qr-size) * 0.05);
/* Theme Variables */
--qr-primary-color: var(--pesaqr-primary-color, #16a34a);
--qr-background: var(--pesaqr-background, white);
--qr-text-color: var(--pesaqr-text-color, white);
--qr-border-color: var(--pesaqr-border-color, #16a34a);
}
/* Dark theme */
:host([theme="dark"]) {
--qr-primary-color: var(--pesaqr-primary-color, #22c55e);
--qr-background: var(--pesaqr-background, #1f2937);
--qr-text-color: var(--pesaqr-text-color, #f3f4f6);
--qr-border-color: var(--pesaqr-border-color, #22c55e);
}
.pesaqr {
position: relative;
border: calc(var(--qr-size) * 0.02) solid var(--qr-border-color);
border-radius: var(--border-radius);
overflow: visible;
width: fit-content;
background: var(--qr-background);
margin-top: calc(var(--header-padding) * 2);
}
.qr-header {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
background: var(--qr-primary-color);
color: var(--qr-text-color);
padding: var(--header-padding) calc(var(--header-padding) * 2);
text-align: center;
user-select: none;
font-weight: bold;
border-radius: calc(var(--border-radius) * 0.35);
font-size: var(--font-size);
white-space: nowrap;
border: calc(var(--qr-size) * 0.02) solid var(--qr-border-color);
}
#qrcode {
display: flex;
justify-content: center;
align-items: center;
}
#qrcode img {
width: var(--qr-size) !important;
height: var(--qr-size) !important;
border-radius: calc(var(--border-radius) * 0.75);
}
`;
__decorate([
property({ type: String })
], PesaQR.prototype, "type", void 0);
__decorate([
property({ type: String })
], PesaQR.prototype, "tillNumber", void 0);
__decorate([
property({ type: String })
], PesaQR.prototype, "paybillNumber", void 0);
__decorate([
property({ type: String })
], PesaQR.prototype, "accountNumber", void 0);
__decorate([
property({ type: String })
], PesaQR.prototype, "phoneNumber", void 0);
__decorate([
property({ type: String })
], PesaQR.prototype, "amount", void 0);
__decorate([
property({ type: Number })
], PesaQR.prototype, "width", void 0);
__decorate([
property({ type: String })
], PesaQR.prototype, "theme", void 0);
__decorate([
property({ type: Boolean })
], PesaQR.prototype, "loading", void 0);
__decorate([
property({ type: String })
], PesaQR.prototype, "error", void 0);
PesaQR = __decorate([
customElement("pesa-qr")
], PesaQR);
export { PesaQR };