diff --git a/composables/useThermalPrint.ts b/composables/useThermalPrint.ts index c71873d..0633ded 100644 --- a/composables/useThermalPrint.ts +++ b/composables/useThermalPrint.ts @@ -28,12 +28,12 @@ export const useThermalPrint = () => { const generateQRCode = async (data: string): Promise => { try { const qrDataUrl = await QRCode.toDataURL(data, { - errorCorrectionLevel: 'H', // High error correction for better scanning reliability + errorCorrectionLevel: 'M', // Medium error correction (better for standard cameras) type: 'image/png', quality: 1, - margin: 0.5, // Reduced margin untuk memperkecil Positioning Detection Markers - width: 100, // Ukuran QR Code untuk thermal printer 80mm - version: 3, // QR Code version 5 (37x37 modules) + margin: 2, // Added margin (quiet zone) for better scanner detection + width: 150, // Slightly larger width for better clarity + version: 3, color: { dark: '#000000', light: '#FFFFFF' diff --git a/nuxt.config.ts b/nuxt.config.ts index 0aed299..cef227b 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -26,23 +26,23 @@ export default defineNuxtConfig({ // @ts-expect-error config.plugins.push(vuetify({ autoImport: true })); - // // Add HTTPS plugin - // try { - // // @ts-ignore - // const { default: basicSsl } = await import('@vitejs/plugin-basic-ssl'); - // // @ts-expect-error - // config.plugins.push(basicSsl()); - // // @ts-expect-error - // config.server = config.server || {}; - // // @ts-expect-error - // config.server.https = true; - // // @ts-expect-error - // config.server.host = '10.10.150.175'; - // // @ts-expect-error - // config.server.port = 3001; - // } catch (e) { - // console.warn('Failed to load HTTPS plugin:', e); - // } + // Add HTTPS plugin + try { + // @ts-ignore + const { default: basicSsl } = await import('@vitejs/plugin-basic-ssl'); + // @ts-expect-error + config.plugins.push(basicSsl()); + // @ts-expect-error + config.server = config.server || {}; + // @ts-expect-error + config.server.https = true; + // @ts-expect-error + config.server.host = '10.10.150.175'; + // @ts-expect-error + config.server.port = 3000; + } catch (e) { + console.warn('Failed to load HTTPS plugin:', e); + } }); }, "nuxt-charts"], @@ -103,6 +103,7 @@ export default defineNuxtConfig({ return { port: port, host: host, + https: false, // Enable HTTPS allowedHosts: ["localhost", "localhost.dev", "10.10.150.175","antrean.dev.rssa.id"] }; })(), diff --git a/package-lock.json b/package-lock.json index dbb88cf..8c79f5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "devDependencies": { "@nuxtjs/google-fonts": "^3.2.0", "@types/node": "^24.7.2", - "@vitejs/plugin-basic-ssl": "^2.1.0", + "@vitejs/plugin-basic-ssl": "^2.1.4", "sass": "^1.93.3", "sass-embedded": "^1.89.2", "vite-plugin-vuetify": "^2.1.2", @@ -7426,9 +7426,9 @@ } }, "node_modules/@vitejs/plugin-basic-ssl": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.3.tgz", - "integrity": "sha512-mxZpCH6SjsAFkiVgaclJGTcYIHm2qxw4x2EP/AUlEVqHhk8ojU75thpvTalc5lAvIK3sJjpVxhzYNoLXOuJGKw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.4.tgz", + "integrity": "sha512-HXciTXN/sDBYWgeAD4V4s0DN0g72x5mlxQhHxtYu3Tt8BLa6MzcJZUyDVFCdtjNs3bfENVHVzOsmooTVuNgAAw==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 3aeb6de..63d0042 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "devDependencies": { "@nuxtjs/google-fonts": "^3.2.0", "@types/node": "^24.7.2", - "@vitejs/plugin-basic-ssl": "^2.1.0", + "@vitejs/plugin-basic-ssl": "^2.1.4", "sass": "^1.93.3", "sass-embedded": "^1.89.2", "vite-plugin-vuetify": "^2.1.2", diff --git a/pages/CheckInPasien/checkIn.vue b/pages/CheckInPasien/checkIn.vue index 09c5580..a102803 100644 --- a/pages/CheckInPasien/checkIn.vue +++ b/pages/CheckInPasien/checkIn.vue @@ -15,7 +15,7 @@ - +
@@ -60,7 +60,7 @@

Kamera tidak terdeteksi

Perangkat Anda tidak memiliki kamera atau kamera tidak dapat diakses. - Silakan gunakan input Manual di sebelah kiri . + Silakan gunakan input Manual di sebelah kanan .

@@ -211,7 +211,7 @@
- + @@ -397,7 +397,6 @@
- @@ -1639,25 +1638,14 @@ const startScanning = async () => { await html5QrCode.start( cameraConfig, { - fps: isMobile.value ? 30 : 30, // FPS tinggi untuk deteksi lebih baik dan smooth + fps: 15, // Reduced FPS improved stability on mobile qrbox: function(viewfinderWidth: number, viewfinderHeight: number) { - // QR box dengan ukuran lebih besar untuk deteksi lebih mudah const minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight); - // Gunakan 80-90% dari viewfinder untuk area scanning yang lebih besar - const percentageSize = Math.floor(minEdgeSize * 0.80); - // Atau ukuran tetap yang lebih besar - const fixedSize = isMobile.value ? 250 : 250; - // Gunakan yang lebih besar antara percentage atau fixed - const qrboxSize = Math.max(percentageSize, fixedSize); - - // Pastikan tidak melebihi viewfinder - const finalSize = Math.min(qrboxSize, minEdgeSize * 0.80); - - console.log('QR Box size:', finalSize, 'Viewfinder:', viewfinderWidth, 'x', viewfinderHeight); - + // Use 70% of the viewfinder for the qrbox to ensure it's comfortably inside + const qrboxSize = Math.floor(minEdgeSize * 0.7); return { - width: Math.max(finalSize, 250), // Minimum 250px untuk deteksi lebih baik - height: Math.max(finalSize, 250) + width: Math.max(qrboxSize, 200), + height: Math.max(qrboxSize, 200) }; }, aspectRatio: 1.0, @@ -2955,12 +2943,11 @@ const generateQRCode = async () => { // Create QR code as data URL (same settings as useThermalPrint) const qrDataUrl = await QRCode.toDataURL(generatedQRData.value, { - errorCorrectionLevel: 'H', + errorCorrectionLevel: 'M', type: 'image/png', quality: 1, - margin: 0.5, - width: 300, // Preview size - version: 3, + margin: 2, + width: 400, // Larger preview size color: { dark: '#000000', light: '#FFFFFF' @@ -4809,26 +4796,14 @@ onUnmounted(() => { } /* Ensure proper column order */ -.content-grid > .v-col[style*="order: 1"] { - order: 1; -} -.content-grid > .v-col[style*="order: 2"] { - order: 2; -} - -.content-grid > .v-col[style*="order: 3"] { - order: 3; -} .sticky-column { position: relative; - order: 1 !important; } /* Manual Input Column */ .content-grid > .v-col:nth-child(2) { - order: 2 !important; } /* QR Scan Card */ @@ -6123,11 +6098,6 @@ onUnmounted(() => { max-width: 100%; max-height: 100%; object-fit: contain; - transform: scaleX(-1); /* Mirror effect */ - -webkit-transform: scaleX(-1); /* Safari support */ - /* Reduce brightness to prevent overexposure/bloom */ - filter: brightness(0.75) contrast(1.1); - -webkit-filter: brightness(0.75) contrast(1.1); } .scanner-instruction { @@ -6220,7 +6190,7 @@ onUnmounted(() => { .qr-scan-card, .manual-input-card { - max-height: calc(100vh - 240px) !important; + max-height: calc(100vh - 200px) !important; overflow-y: auto; } @@ -6237,13 +6207,11 @@ onUnmounted(() => { } .sticky-column { - order: 1 !important; flex-shrink: 0; flex-basis: auto; } .content-grid > .v-col:nth-child(2) { - order: 2 !important; flex-shrink: 0; flex-basis: auto; } @@ -6376,8 +6344,8 @@ onUnmounted(() => { /* Stats Footer Horizontal - Permanent Footer for All Screens */ .stats-footer-row { - margin-top: 4px !important; - margin-bottom: 4px !important; + margin-top: 0px !important; + margin-bottom: 2px !important; flex-shrink: 0; display: flex; justify-content: center; @@ -6531,11 +6499,21 @@ onUnmounted(() => { .qr-reader-wrapper :deep(video) { max-width: 100%; max-height: 100%; - transform: scaleX(-1); /* Mirror effect */ - -webkit-transform: scaleX(-1); /* Safari support */ - /* Reduce brightness to prevent overexposure/bloom */ - filter: brightness(0.75) contrast(1.1); - -webkit-filter: brightness(0.75) contrast(1.1); + object-fit: contain; } } + +.qr-code-container { + background: white; + padding: 12px; + border-radius: 12px; + display: inline-block; + margin: 0 auto; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); +} + +.qr-code-container img { + display: block; + margin: 0 auto; +} \ No newline at end of file