// src/stores/payment.ts import { defineStore } from 'pinia'; // 1. Definisikan Tipe Data untuk qrData (penting untuk properti expired_at yang di-spread) 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/Expired ip: string | null; // Tambahkan properti yang di-spread dari API, termasuk expired_at expired_at?: string; // Tambahkan expired_at sebagai properti opsional [key: string]: any; // Indeks signature untuk properti dinamis (misal: transaction_id, reason) } // 2. Definisikan Tipe Data untuk State interface PaymentState { currentStep: 1 | 2 | 3 | 4; patientInfo: { name: string; amount: string; expiry: string; }; qrData: QrData; } // Variabel di luar store untuk menyimpan timer, agar persistensi di luar state Pinia let autoResetTimer: number | null = null; export const usePaymentStore = defineStore('payment', { state: (): PaymentState => ({ // Gunakan tipedata PaymentState currentStep: 1, // 1: Menunggu Data, 2: Tampilkan QRIS, 3: Sukses, 4: Gagal patientInfo: { name: '', amount: '', expiry: '', // Waktu kedaluwarsa diambil dari qrData (via spread) }, qrData: { qrvalue: null, display_nobill: null, display_name: null, display_amount: null, status: null, ip: null, // created_at DIHAPUS } as QrData, // Type casting untuk 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 (50s) for reset.'); // Di TypeScript, setTimeout mengembalikan number 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, // created_at DIHAPUS ...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'); } // Perlu pengecekan properti qr_code pada apiData, bukan state if (!this.qrData.qrvalue) { issues.push('QR code missing'); } if (issues.length > 0) { console.warn('Data validation issues:', issues); return false; } return true; } }, });