190 lines
6.3 KiB
Vue
190 lines
6.3 KiB
Vue
<!-- Komponen ini digunakan jika menggunakan library @mmote/niimbluelib -->
|
|
<template>
|
|
<div v-if="show" class="fixed inset-0 bg-black/75 flex items-center justify-center p-4 z-50 backdrop-blur-sm">
|
|
<div class="bg-white rounded-xl shadow-lg max-w-md w-full p-6 relative transform transition-all duration-300">
|
|
<!-- Header -->
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-lg font-bold text-D">
|
|
<i class="fas fa-print mr-2"></i>
|
|
Koneksi Printer Niimbot
|
|
</h3>
|
|
<button @click="$emit('close')" class="text-gray-400 hover:text-gray-600">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Connection Status -->
|
|
<div class="mb-4">
|
|
<div v-if="isConnected" class="flex items-center justify-between p-3 bg-green-50 border border-green-200 rounded-lg">
|
|
<div class="flex items-center gap-2">
|
|
<div class="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
|
|
<div>
|
|
<div class="font-medium text-green-900">Terhubung</div>
|
|
<div class="text-sm text-green-700">{{ connectedPrinterName }}</div>
|
|
</div>
|
|
</div>
|
|
<button @click="handleDisconnect" class="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 transition text-sm">
|
|
<i class="fas fa-power-off mr-1"></i>
|
|
Putus
|
|
</button>
|
|
</div>
|
|
|
|
<div v-else-if="connectionState === 'connecting'" class="flex items-center gap-2 p-3 bg-blue-50 border border-blue-200 rounded-lg">
|
|
<div class="animate-spin rounded-full h-5 w-5 border-b-2 border-blue-600"></div>
|
|
<span class="text-blue-900">Menghubungkan...</span>
|
|
</div>
|
|
|
|
<div v-else class="p-3 bg-gray-50 border border-gray-200 rounded-lg">
|
|
<div class="text-gray-600 text-sm mb-2">Status: Tidak terhubung</div>
|
|
|
|
<!-- Connection Type Selector -->
|
|
<div class="flex gap-2 mb-3">
|
|
<button
|
|
v-if="featureSupport.webBluetooth"
|
|
@click="connectionType = 'bluetooth'"
|
|
:class="[
|
|
'flex-1 px-3 py-2 rounded border transition text-sm',
|
|
connectionType === 'bluetooth'
|
|
? 'bg-D text-white border-D'
|
|
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'
|
|
]">
|
|
<i class="fab fa-bluetooth-b mr-1"></i>
|
|
Bluetooth
|
|
</button>
|
|
|
|
<button
|
|
v-if="featureSupport.webSerial"
|
|
@click="connectionType = 'serial'"
|
|
:class="[
|
|
'flex-1 px-3 py-2 rounded border transition text-sm',
|
|
connectionType === 'serial'
|
|
? 'bg-D text-white border-D'
|
|
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'
|
|
]">
|
|
<i class="fas fa-usb mr-1"></i>
|
|
USB
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Connect Button -->
|
|
<button
|
|
@click="handleConnect"
|
|
:disabled="!canConnect"
|
|
:class="[
|
|
'w-full px-4 py-2 rounded transition flex items-center justify-center',
|
|
canConnect
|
|
? 'bg-D text-white hover:bg-D/80'
|
|
: 'bg-gray-300 text-gray-500 cursor-not-allowed'
|
|
]">
|
|
<i class="fas fa-power mr-2"></i>
|
|
Hubungkan Printer
|
|
</button>
|
|
|
|
<div v-if="!canConnect" class="text-xs text-red-500 mt-2 text-center">
|
|
Browser Anda tidak mendukung koneksi printer
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Printer Info (when connected) -->
|
|
<div v-if="isConnected && printerInfo" class="mb-4">
|
|
<button
|
|
@click="showDetails = !showDetails"
|
|
class="w-full flex items-center justify-between p-2 bg-gray-50 rounded hover:bg-gray-100 transition">
|
|
<span class="text-sm font-medium text-D">Detail Printer</span>
|
|
<i :class="['fas transition-transform', showDetails ? 'fa-chevron-up' : 'fa-chevron-down']"></i>
|
|
</button>
|
|
|
|
<div v-if="showDetails" class="mt-2 p-3 bg-gray-50 rounded text-sm">
|
|
<div v-for="(value, key) in printerInfo" :key="key" class="flex justify-between py-1">
|
|
<span class="text-gray-600">{{ key }}:</span>
|
|
<span class="font-medium text-D">{{ value || '-' }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Error Display -->
|
|
<div v-if="error" class="mb-4 p-3 bg-red-50 border border-red-200 rounded text-sm text-red-700">
|
|
<i class="fas fa-exclamation-triangle mr-2"></i>
|
|
{{ error }}
|
|
</div>
|
|
|
|
<!-- Help Text -->
|
|
<div class="text-xs text-gray-500 p-3 bg-gray-50 rounded">
|
|
<i class="fas fa-info-circle mr-1"></i>
|
|
<strong>Tips:</strong> Pastikan printer Niimbot sudah dihidupkan dan mode pairing aktif (untuk Bluetooth) atau terhubung via USB.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, watch } from 'vue';
|
|
import { useNiimbotPrinter } from '../composables/useNiimbotPrinter';
|
|
|
|
const props = defineProps({
|
|
show: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
});
|
|
|
|
const emit = defineEmits(['close', 'connected', 'disconnected']);
|
|
|
|
// Use Niimbot composable
|
|
const {
|
|
connectionState,
|
|
connectedPrinterName,
|
|
printerInfo,
|
|
printerMeta,
|
|
isConnected,
|
|
isDisconnected,
|
|
featureSupport,
|
|
connectionType,
|
|
initClient,
|
|
connect,
|
|
disconnect,
|
|
} = useNiimbotPrinter();
|
|
|
|
// Local state
|
|
const error = ref('');
|
|
const showDetails = ref(false);
|
|
|
|
// Computed
|
|
const canConnect = computed(() => {
|
|
return featureSupport.value.webBluetooth || featureSupport.value.webSerial;
|
|
});
|
|
|
|
// Methods
|
|
const handleConnect = async () => {
|
|
error.value = '';
|
|
try {
|
|
await connect();
|
|
emit('connected');
|
|
} catch (err) {
|
|
console.error('Connection error:', err);
|
|
error.value = err.message || 'Gagal terhubung ke printer. Pastikan printer sudah dinyalakan dan dalam mode pairing.';
|
|
}
|
|
};
|
|
|
|
const handleDisconnect = () => {
|
|
disconnect();
|
|
emit('disconnected');
|
|
error.value = '';
|
|
};
|
|
|
|
// Watch connection state changes
|
|
watch(isConnected, (newVal) => {
|
|
if (newVal) {
|
|
error.value = '';
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: scale(0.95); }
|
|
to { opacity: 1; transform: scale(1); }
|
|
}
|
|
</style>
|