212 lines
5.9 KiB
TypeScript
212 lines
5.9 KiB
TypeScript
// src/stores/payment.ts
|
|
import { defineStore } from "pinia";
|
|
|
|
// definisi tipe data
|
|
interface QrData {
|
|
qrvalue: string | null;
|
|
display_nobill: string | null;
|
|
display_name: string | null;
|
|
display_amount: string | null;
|
|
status: "1" | "2" | "0" | null; // "1": Pending, "2": Sukses, "0": Gagal/Pending
|
|
ip: string | null;
|
|
expired_at?: string;
|
|
[key: string]: any; // Indeks signature untuk properti dinamis (misal: transaction_id, reason)
|
|
}
|
|
|
|
// definisi tipe data untuk State
|
|
interface PaymentState {
|
|
currentStep: 1 | 2 | 3 | 4;
|
|
patientInfo: {
|
|
name: string;
|
|
amount: string;
|
|
expiry: string;
|
|
};
|
|
qrData: QrData;
|
|
}
|
|
|
|
let autoResetTimer: number | null = null;
|
|
|
|
export const usePaymentStore = defineStore("payment", {
|
|
state: (): PaymentState => ({
|
|
currentStep: 1, // 1: Menunggu Data, 2: Tampilkan QRIS, 3: Sukses, 4: Gagal/Pending
|
|
patientInfo: {
|
|
name: "",
|
|
amount: "",
|
|
expiry: "",
|
|
},
|
|
qrData: {
|
|
qrvalue: null,
|
|
display_nobill: null,
|
|
display_name: null,
|
|
display_amount: null,
|
|
status: null,
|
|
ip: null,
|
|
} as QrData,
|
|
}),
|
|
|
|
getters: {
|
|
hasQrData: (state): boolean => !!state.qrData.qrvalue,
|
|
safeQrValue: (state): string =>
|
|
state.qrData.qrvalue || "https://www.google.com",
|
|
|
|
isReadyForStatusCheck: (state): boolean => {
|
|
return !!(state.qrData.display_nobill && state.qrData.display_name);
|
|
},
|
|
|
|
debugInfo: (state) => ({
|
|
step: state.currentStep,
|
|
hasIdentifiers: !!(
|
|
state.qrData.display_nobill && state.qrData.display_name
|
|
),
|
|
qrData: state.qrData,
|
|
patientInfo: state.patientInfo,
|
|
}),
|
|
},
|
|
|
|
actions: {
|
|
nextStep() {
|
|
this.currentStep++;
|
|
},
|
|
prevStep() {
|
|
this.currentStep--;
|
|
},
|
|
|
|
setStep(step: 1 | 2 | 3 | 4) {
|
|
console.log(`[STORE] Setting step from ${this.currentStep} to ${step}`);
|
|
this.currentStep = step;
|
|
},
|
|
|
|
startAutoReset() {
|
|
if (autoResetTimer) {
|
|
clearTimeout(autoResetTimer);
|
|
}
|
|
console.log("🏠 [STORE] Starting auto return timer (10s) for reset.");
|
|
|
|
autoResetTimer = setTimeout(() => {
|
|
console.log("🏠 [STORE] Auto return to home triggered");
|
|
this.reset();
|
|
}, 10000);
|
|
},
|
|
|
|
reset() {
|
|
console.log("--- [STORE] Resetting payment store ---");
|
|
this.currentStep = 1;
|
|
this.patientInfo = {
|
|
name: "",
|
|
amount: "",
|
|
expiry: "",
|
|
};
|
|
this.qrData = {
|
|
qrvalue: null,
|
|
display_nobill: null,
|
|
display_name: null,
|
|
display_amount: null,
|
|
status: null,
|
|
ip: null,
|
|
} as QrData; // Pastikan tipe kembali ke QrData
|
|
if (autoResetTimer) {
|
|
clearTimeout(autoResetTimer);
|
|
autoResetTimer = null;
|
|
}
|
|
},
|
|
|
|
// Definisikan tipe untuk apiResponse
|
|
updatePayment(apiResponse: { data: QrData[] }) {
|
|
console.log("=== [STORE] UPDATE PAYMENT ===");
|
|
|
|
if (!apiResponse?.data || apiResponse.data.length === 0) {
|
|
console.error("Invalid API response structure or empty data array");
|
|
return;
|
|
}
|
|
|
|
const apiData = apiResponse.data[0];
|
|
const oldStatus = this.qrData.status;
|
|
|
|
// Update qrData dengan semua properti dari API
|
|
this.qrData = {
|
|
qrvalue: apiData.qrvalue || apiData.qr_code || this.qrData.qrvalue,
|
|
display_nobill: apiData.display_nobill || this.qrData.display_nobill,
|
|
display_name: apiData.display_name || this.qrData.display_name,
|
|
display_amount:
|
|
apiData.display_amount ||
|
|
apiData.nominal ||
|
|
this.qrData.display_amount,
|
|
status: (apiData.status as QrData["status"]) || this.qrData.status, // Type casting untuk status
|
|
ip: apiData.ip || this.qrData.ip,
|
|
|
|
...apiData, // expired_at akan masuk di sini
|
|
};
|
|
|
|
// Update patientInfo
|
|
this.patientInfo = {
|
|
name: this.qrData.display_name || this.patientInfo.name || "Unknown",
|
|
amount: this.qrData.display_amount || this.patientInfo.amount || "0",
|
|
expiry: this.patientInfo.expiry,
|
|
};
|
|
|
|
// --- LOGIKA TRANSISI STATUS OTOMATIS (SUCCESS/FAIL) ---
|
|
const newStatus = this.qrData.status;
|
|
|
|
if (oldStatus !== newStatus) {
|
|
console.log(`[STORE] Status changed: ${oldStatus} -> ${newStatus}`);
|
|
}
|
|
|
|
if (this.currentStep === 2 && oldStatus !== newStatus) {
|
|
if (newStatus === "2") {
|
|
console.log(
|
|
"🎉 [STORE] Status 2 (SUKSES) diterima. Pindah ke Step 3."
|
|
);
|
|
this.currentStep = 3;
|
|
this.startAutoReset();
|
|
} else if (newStatus === "0") {
|
|
console.log(
|
|
"❌ [STORE] Status 0 (GAGAL) diterima. Pindah ke Step 4."
|
|
);
|
|
this.currentStep = 4;
|
|
this.startAutoReset();
|
|
}
|
|
}
|
|
|
|
console.log("Updated qrData:", this.qrData);
|
|
console.log("Updated patientInfo:", this.patientInfo);
|
|
console.log("===================");
|
|
},
|
|
|
|
// Method untuk debug
|
|
debugCurrentState() {
|
|
console.log("=== PAYMENT STORE DEBUG ===");
|
|
console.log("Current Step:", this.currentStep);
|
|
console.log("Patient Info:", this.patientInfo);
|
|
console.log("QR Data:", this.qrData);
|
|
console.log("Has QR Data:", this.hasQrData);
|
|
console.log("Ready for Status Check:", this.isReadyForStatusCheck);
|
|
console.log("Safe QR Value:", this.safeQrValue);
|
|
console.log("==========================");
|
|
},
|
|
|
|
// Method untuk validasi data
|
|
validateData(): boolean {
|
|
const issues: string[] = [];
|
|
|
|
if (!this.qrData.display_nobill) {
|
|
issues.push("display_nobill missing");
|
|
}
|
|
|
|
if (!this.qrData.display_name) {
|
|
issues.push("display_name missing");
|
|
}
|
|
|
|
if (!this.qrData.qrvalue) {
|
|
issues.push("QR code missing");
|
|
}
|
|
|
|
if (issues.length > 0) {
|
|
console.warn("Data validation issues:", issues);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
},
|
|
});
|