status check
This commit is contained in:
@@ -134,6 +134,9 @@
|
|||||||
</button>
|
</button>
|
||||||
<p class="qr-modal__label">{{ 'create.qr_label' | translate }}</p>
|
<p class="qr-modal__label">{{ 'create.qr_label' | translate }}</p>
|
||||||
<img class="qr-modal__img" [src]="qrImageUrl()!" width="260" height="260" alt="QR" />
|
<img class="qr-modal__img" [src]="qrImageUrl()!" width="260" height="260" alt="QR" />
|
||||||
|
@if (qrStatus()) {
|
||||||
|
<span class="qr-modal__status">{{ qrStatus() }}</span>
|
||||||
|
}
|
||||||
@if (qrPolling()) {
|
@if (qrPolling()) {
|
||||||
<p class="qr-modal__hint">{{ 'create.qr_waiting' | translate }}</p>
|
<p class="qr-modal__hint">{{ 'create.qr_waiting' | translate }}</p>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,6 +237,17 @@
|
|||||||
color: #64748b;
|
color: #64748b;
|
||||||
animation: pulse 1.6s ease-in-out infinite;
|
animation: pulse 1.6s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__status {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes overlay-in {
|
@keyframes overlay-in {
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ interface CreateQrResponse {
|
|||||||
Payload?: string; // per API doc (capital P)
|
Payload?: string; // per API doc (capital P)
|
||||||
nspkurl?: string; // actual field name in real responses
|
nspkurl?: string; // actual field name in real responses
|
||||||
qrUrl?: string;
|
qrUrl?: string;
|
||||||
qrStatus?: string;
|
status?: string; // e.g. "REGISTERED"
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QrStatusResponse {
|
interface QrStatusResponse {
|
||||||
status?: string; // "NEW" | "APPROVED" | "REJECTED" | "COMPLETED"
|
status?: string; // "REGISTERED" | "NEW" | "APPROVED" | "REJECTED" | "COMPLETED"
|
||||||
nspkurl?: string;
|
nspkurl?: string;
|
||||||
nspkID?: string;
|
nspkID?: string;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
@@ -88,6 +88,7 @@ export class CreatePage {
|
|||||||
// QR display state
|
// QR display state
|
||||||
qrImageUrl = signal<string | null>(null);
|
qrImageUrl = signal<string | null>(null);
|
||||||
qrPolling = signal<boolean>(false);
|
qrPolling = signal<boolean>(false);
|
||||||
|
qrStatus = signal<string>('');
|
||||||
private pollHandle: ReturnType<typeof setInterval> | null = null;
|
private pollHandle: ReturnType<typeof setInterval> | null = null;
|
||||||
private activeQrId = '';
|
private activeQrId = '';
|
||||||
|
|
||||||
@@ -160,6 +161,7 @@ export class CreatePage {
|
|||||||
const qrId = res?.qrId ?? res?.nspkID ?? '';
|
const qrId = res?.qrId ?? res?.nspkID ?? '';
|
||||||
// Real API uses 'nspkurl'; doc says 'Payload' — try both
|
// Real API uses 'nspkurl'; doc says 'Payload' — try both
|
||||||
const nspkUrl = res?.nspkurl ?? res?.Payload;
|
const nspkUrl = res?.nspkurl ?? res?.Payload;
|
||||||
|
this.qrStatus.set(res?.status ?? '');
|
||||||
if (qrId || nspkUrl) {
|
if (qrId || nspkUrl) {
|
||||||
this.activeQrId = qrId;
|
this.activeQrId = qrId;
|
||||||
const qrData = nspkUrl
|
const qrData = nspkUrl
|
||||||
@@ -186,19 +188,21 @@ export class CreatePage {
|
|||||||
this.http.get<QrStatusResponse>(`${QR_VITANOVA_API}/qr/dynamic/${qrId}`)
|
this.http.get<QrStatusResponse>(`${QR_VITANOVA_API}/qr/dynamic/${qrId}`)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
// API returns status: "NEW" | "APPROVED" | "REJECTED" | "COMPLETED"
|
const st = res?.status ?? '';
|
||||||
if (res?.status === 'COMPLETED' || res?.status === 'APPROVED') {
|
this.qrStatus.set(st);
|
||||||
|
if (st === 'COMPLETED' || st === 'APPROVED') {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
this.createFastcheck();
|
this.createFastcheck();
|
||||||
} else if (res?.status === 'REJECTED') {
|
} else if (st === 'REJECTED') {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
this.error.set(this.t('errors.payment_failed'));
|
this.error.set(this.t('errors.payment_failed'));
|
||||||
this.qrImageUrl.set(null);
|
this.qrImageUrl.set(null);
|
||||||
}
|
}
|
||||||
|
// REGISTERED / NEW / '' — keep polling
|
||||||
},
|
},
|
||||||
error: () => undefined
|
error: () => undefined
|
||||||
});
|
});
|
||||||
}, 3000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private stopPolling(): void {
|
private stopPolling(): void {
|
||||||
@@ -247,6 +251,7 @@ export class CreatePage {
|
|||||||
closeQr(): void {
|
closeQr(): void {
|
||||||
this.qrImageUrl.set(null);
|
this.qrImageUrl.set(null);
|
||||||
this.qrPolling.set(false);
|
this.qrPolling.set(false);
|
||||||
|
this.qrStatus.set('');
|
||||||
if (this.pollHandle !== null) {
|
if (this.pollHandle !== null) {
|
||||||
clearInterval(this.pollHandle);
|
clearInterval(this.pollHandle);
|
||||||
this.pollHandle = null;
|
this.pollHandle = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user