+
+
+
+
+
+
+
+
+
+
![QR Code]()
+
+
+
+
+
+ QRIS
+
+
-
+
+
+
+
mdi-qrcode-scan
+
Arahkan kamera ke QR code
+
+
+
+
+
+
+
+
+
+
+
+ mdi-account-outline
+ Nama Pasien
+
+
+ {{ paymentStore.patientInfo.name }}
+
+
+
+
+
+ mdi-cash
+ Nominal
+
+
+ {{ formatCurrency(paymentStore.patientInfo.amount) }}
+
+
+
+
+
+ mdi-file-document-outline
+ Nomor Tagihan
+
+
+ {{ paymentStore.qrData.display_nobill }}
+
+
+
+
+
+ mdi-clock-outline
+ Berlaku Sampai
+
+
Tidak terbatas
+
+
+
+
+
+
+
+
+
Menunggu pembayaran...
+
+
+ mdi-clock-fast
+ Pending
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- NAMA PASIEN:
-
-
- {{ paymentStore.patientInfo.name }}
-
-
-
-
-
- NOMINAL:
-
-
- {{ paymentStore.patientInfo.amount }}
-
-
-
-
-
- NOMOR TAGIHAN:
-
-
- {{ paymentStore.qrData.display_nobill }}
-
-
-
-
-
- BERLAKU SAMPAI:
-
- N/A
-
-
-
-
-
-
+
+
+
+ mdi-play-circle-outline
Simulasi Pembayaran
+
+
+
+ mdi-information-outline
+ Scan QR code menggunakan aplikasi pembayaran digital Anda
+
\ No newline at end of file
+
+/* QR Instructions */
+.qr-instructions {
+ margin-top: 1rem;
+}
+
+.instruction-text {
+ color: #666;
+ font-size: 0.9rem;
+ font-weight: 500;
+ margin: 0;
+}
+
+/* Payment Details Card */
+.payment-details-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20px;
+ padding: 2rem;
+ backdrop-filter: blur(20px);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ box-shadow:
+ 0 8px 32px rgba(0, 0, 0, 0.06),
+ inset 0 1px 0 rgba(255, 255, 255, 0.8);
+ height: fit-content;
+ width: 100%;
+}
+
+.details-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 1.5rem;
+ padding-bottom: 1rem;
+ border-bottom: 2px solid rgba(0, 0, 0, 0.06);
+}
+
+.details-title {
+ font-weight: 700;
+ color: #1a1a1a;
+ font-size: 1.2rem;
+}
+
+.details-content {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.detail-row {
+ display: flex;
+ flex-direction: column;
+ gap: 0.2rem;
+ padding: 0.5rem;
+ border-radius: 12px;
+ background: rgba(248, 250, 252, 0.6);
+ border: 1px solid rgba(0, 0, 0, 0.04);
+ transition: all 0.3s ease;
+}
+
+.detail-row:hover {
+ background: rgba(248, 250, 252, 0.9);
+ transform: translateY(-1px);
+}
+
+.highlight-row {
+ background: rgba(46, 204, 113, 0.08) !important;
+ border: 1px solid rgba(46, 204, 113, 0.2) !important;
+}
+
+.highlight-row:hover {
+ background: rgba(46, 204, 113, 0.12) !important;
+}
+
+.detail-label {
+ display: flex;
+ align-items: center;
+ color: #666;
+ font-size: 0.8rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.detail-value {
+ color: #1a1a1a;
+ font-weight: 700;
+ font-size: 1.1rem;
+ margin-left: 1.5rem;
+}
+
+.detail-value.patient-name {
+ color: #2c3e50;
+ font-size: 1.2rem;
+}
+
+.detail-value.amount {
+ color: #27ae60;
+ font-size: 1.4rem;
+ font-weight: 800;
+}
+
+.detail-value.expired {
+ color: #e67e22;
+ font-size: 1rem;
+}
+
+/* Payment Status */
+.payment-status {
+ padding: 1rem;
+ background: rgba(255, 193, 7, 0.08);
+ border-radius: 12px;
+ border: 1px solid rgba(255, 193, 7, 0.2);
+}
+
+.status-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.status-indicator-inline {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+/* Status Indicator */
+.status-indicator {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+}
+
+.status-dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: #f39c12;
+}
+
+.status-dot.pulsing {
+ animation: pulse 1.5s ease-in-out infinite;
+}
+
+@keyframes pulse {
+ 0%,
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+ 50% {
+ opacity: 0.5;
+ transform: scale(1.2);
+ }
+}
+
+.status-text {
+ color: #666;
+ font-size: 0.9rem;
+ font-weight: 500;
+}
+
+/* Action Buttons */
+.action-buttons {
+ display: flex;
+ gap: 1rem;
+ justify-content: center;
+}
+
+.action-btn {
+ border-radius: 16px !important;
+ font-weight: 600 !important;
+ text-transform: none !important;
+ padding: 0 2rem !important;
+ min-width: 140px;
+ transition: all 0.3s ease !important;
+}
+
+.back-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15) !important;
+}
+
+.simulate-btn {
+ background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%) !important;
+ box-shadow: 0 4px 15px rgba(46, 204, 113, 0.3) !important;
+}
+
+.simulate-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 8px 25px rgba(46, 204, 113, 0.4) !important;
+}
+
+/* Help Text */
+.help-text {
+ color: #888;
+ font-size: 0.8rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.25rem;
+}
+
+/* Responsive Design */
+@media (max-width: 900px) {
+ .content-grid {
+ grid-template-columns: 1fr;
+ gap: 2rem;
+ }
+
+ .qr-container {
+ max-width: 320px;
+ }
+
+ .payment-details-card {
+ width: 100%;
+ }
+}
+
+@media (max-width: 480px) {
+ .qr-container {
+ padding: 1.5rem;
+ max-width: 280px;
+ }
+
+ .qr-image {
+ width: 200px;
+ height: 200px;
+ }
+
+ .action-buttons {
+ flex-direction: column;
+ }
+
+ .action-btn {
+ min-width: 100%;
+ }
+
+ .payment-title {
+ font-size: 1.3rem;
+ }
+
+ .payment-details-card {
+ padding: 1.5rem;
+ }
+}
+
+/* Tablet Landscape Optimization */
+@media (orientation: landscape) and (min-width: 768px) and (max-height: 600px) {
+ .header-section {
+ padding-top: 0.5rem;
+ margin-bottom: 2rem;
+ }
+
+ .payment-title {
+ font-size: 1.3rem;
+ margin-bottom: 0.25rem;
+ }
+
+ .payment-subtitle {
+ font-size: 0.8rem;
+ }
+
+ .qr-container {
+ padding: 1.5rem;
+ }
+
+ .qr-image {
+ width: 200px;
+ height: 200px;
+ }
+
+ .payment-details-card {
+ padding: 1.5rem;
+ min-height: 300px;
+ }
+
+ .content-grid {
+ gap: 2rem;
+ }
+}
+
+/* Large Tablet Landscape */
+@media (orientation: landscape) and (min-width: 1024px) {
+ .content-grid {
+ max-width: 1200px;
+ gap: 4rem;
+ }
+
+ .qr-container {
+ max-width: 400px;
+ }
+
+ .qr-image {
+ width: 280px;
+ height: 280px;
+ }
+
+ .payment-details-card {
+ width: 100%;
+ }
+}
+
diff --git a/pages/index.vue b/pages/index.vue
index 6973155..e0e1a17 100644
--- a/pages/index.vue
+++ b/pages/index.vue
@@ -1,8 +1,8 @@
-
-
-
+
+
+
!!localIpAddress.value);
-const apiURL = 'http://10.10.150.68:8084/api/v1/qris/allstatus';
+const apiURL = 'http://10.10.150.67:8084/api/v1/qris/allstatus';
const paymentSteps = {
1: Home,
@@ -114,7 +114,7 @@ const startPolling = () => {
console.log(`📊 Found ${samePatientRecords.length} records for same patient:`,
samePatientRecords.map(r => `status: ${r.status}`));
- // Now look for final status (success or fail) among same patient records
+
const successRecord = samePatientRecords.find(record => record.status === "2");
const failRecord = samePatientRecords.find(record => record.status === "0");
@@ -124,12 +124,12 @@ const startPolling = () => {
paymentStore.currentStep = 3;
clearInterval(pollingInterval.value);
- // Auto return to home after 5 seconds
+
setTimeout(() => {
console.log('🏠 Auto return to home');
paymentStore.reset();
startPolling();
- }, 10000);
+ }, 20000);
} else if (failRecord) {
console.log('❌ FAIL STATUS FOUND!', failRecord);
@@ -137,12 +137,12 @@ const startPolling = () => {
paymentStore.currentStep = 4;
clearInterval(pollingInterval.value);
- // Auto return to home after 5 seconds
+
setTimeout(() => {
console.log('🏠 Auto return to home');
paymentStore.reset();
startPolling();
- }, 10000);
+ }, 20000);
} else {
console.log('⏳ Still waiting for final status...');
@@ -156,7 +156,7 @@ const startPolling = () => {
} catch (error) {
console.error("❌ Polling error:", error);
}
- }, 10000);
+ }, 20000);
console.log(`🚀 Polling started - IP-based patient detection`);
};
@@ -165,7 +165,7 @@ const checkAndRedirect = () => {
const savedIp = localStorage.getItem('loketIp');
if (!savedIp) {
console.warn('IP Address belum diatur. Mengarahkan ke halaman setup.');
- router.push('/setup-ip');
+ router.push('/setupip');
} else {
localIpAddress.value = savedIp;
console.log('IP Address ditemukan:', savedIp);
@@ -189,19 +189,62 @@ onUnmounted(() => {
\ No newline at end of file