feat(rcart): persist payment request ID in URL for reloadability
After generating a payment request, push ?id=<paymentId> into the URL. On page load, if ?id= is present, fetch the payment from the API and display the QR/share view directly. Reset clears the URL param. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5d019566f3
commit
71b2acd47b
|
|
@ -30,6 +30,7 @@ class FolkPaymentRequest extends HTMLElement {
|
|||
private enabledMethods = { card: true, wallet: true, encryptid: true };
|
||||
|
||||
// Result state
|
||||
private loading = false;
|
||||
private generating = false;
|
||||
private generatedPayment: any = null;
|
||||
private qrDataUrl = '';
|
||||
|
|
@ -50,7 +51,14 @@ class FolkPaymentRequest extends HTMLElement {
|
|||
connectedCallback() {
|
||||
this.space = this.getAttribute('space') || 'default';
|
||||
this.checkExistingSession();
|
||||
this.render();
|
||||
|
||||
// Restore payment from URL if present (e.g. ?id=abc-123)
|
||||
const urlId = new URLSearchParams(window.location.search).get('id');
|
||||
if (urlId) {
|
||||
this.loadExistingPayment(urlId);
|
||||
} else {
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
private getApiBase(): string {
|
||||
|
|
@ -134,6 +142,48 @@ class FolkPaymentRequest extends HTMLElement {
|
|||
this.render();
|
||||
}
|
||||
|
||||
// ── Load existing payment from URL ──
|
||||
|
||||
private async loadExistingPayment(paymentId: string) {
|
||||
this.loading = true;
|
||||
this.render();
|
||||
|
||||
try {
|
||||
const res = await fetch(`${this.getApiBase()}/api/payments/${paymentId}`);
|
||||
if (!res.ok) throw new Error('Payment not found');
|
||||
const data = await res.json();
|
||||
|
||||
this.generatedPayment = data;
|
||||
this.description = data.description || '';
|
||||
this.amount = data.amount || '';
|
||||
this.amountEditable = data.amountEditable || false;
|
||||
this.token = data.token || 'USDC';
|
||||
this.chainId = data.chainId || 8453;
|
||||
this.paymentType = data.paymentType || 'single';
|
||||
this.maxPayments = data.maxPayments || 0;
|
||||
this.enabledMethods = data.enabledMethods || { card: true, wallet: true, encryptid: true };
|
||||
this.authenticated = true; // skip auth since we're viewing
|
||||
|
||||
// Build URLs
|
||||
const host = window.location.origin;
|
||||
this.payUrl = `${host}/${this.space}/rcart/pay/${paymentId}`;
|
||||
this.qrSvgUrl = `${host}/${this.space}/rcart/api/payments/${paymentId}/qr`;
|
||||
|
||||
// Generate client-side QR
|
||||
try {
|
||||
const QRCode = await import('qrcode');
|
||||
this.qrDataUrl = await QRCode.toDataURL(this.payUrl, {
|
||||
margin: 2, width: 280,
|
||||
color: { dark: '#1e1b4b', light: '#ffffff' },
|
||||
});
|
||||
} catch { /* QR generation optional */ }
|
||||
} catch (e) {
|
||||
this.authError = e instanceof Error ? e.message : String(e);
|
||||
}
|
||||
this.loading = false;
|
||||
this.render();
|
||||
}
|
||||
|
||||
// ── Generate payment request ──
|
||||
|
||||
private async generatePayment() {
|
||||
|
|
@ -188,6 +238,11 @@ class FolkPaymentRequest extends HTMLElement {
|
|||
color: { dark: '#1e1b4b', light: '#ffffff' },
|
||||
});
|
||||
} catch { /* QR generation optional */ }
|
||||
|
||||
// Update URL so page can be reloaded
|
||||
const newUrl = new URL(window.location.href);
|
||||
newUrl.searchParams.set('id', this.generatedPayment.id);
|
||||
history.pushState(null, '', newUrl.toString());
|
||||
} catch (e) {
|
||||
this.authError = e instanceof Error ? e.message : String(e);
|
||||
}
|
||||
|
|
@ -206,6 +261,12 @@ class FolkPaymentRequest extends HTMLElement {
|
|||
this.paymentType = 'single';
|
||||
this.maxPayments = 0;
|
||||
this.enabledMethods = { card: true, wallet: true, encryptid: true };
|
||||
|
||||
// Clear URL param
|
||||
const newUrl = new URL(window.location.href);
|
||||
newUrl.searchParams.delete('id');
|
||||
history.pushState(null, '', newUrl.toString());
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +279,8 @@ class FolkPaymentRequest extends HTMLElement {
|
|||
<h1 class="page-title">Request Payment</h1>
|
||||
<p class="page-subtitle">Generate a QR code anyone can scan to pay you</p>
|
||||
|
||||
${this.generatedPayment ? this.renderResult() :
|
||||
${this.loading ? '<p style="text-align:center;color:var(--rs-text-secondary)">Loading payment...</p>' :
|
||||
this.generatedPayment ? this.renderResult() :
|
||||
!this.authenticated ? this.renderAuthStep() :
|
||||
this.renderForm()}
|
||||
</div>`;
|
||||
|
|
|
|||
Loading…
Reference in New Issue