store/resources/js/components/admin/manage/orders/ThermalPrinterConnectButton.vue

131 lines
3.8 KiB
Vue

<script setup lang="ts">
import { Bluetooth, PlugZap, Usb } from '@lucide/vue';
import { onMounted, ref } from 'vue';
import { toast } from 'vue-sonner';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { useThermalPrinter } from '@/composables/useThermalPrinter';
const open = ref(false);
const {
isConnected,
connectionLabel,
connecting,
connectUsb,
connectBluetooth,
tryReconnect,
disconnect,
supportsUsb,
supportsBluetooth,
} = useThermalPrinter();
onMounted(async () => {
await tryReconnect();
});
async function handleConnectUsb() {
try {
await connectUsb();
open.value = false;
toast.success('Printer USB terhubung.');
} catch (error) {
const message = error instanceof Error
? error.message
: 'Gagal menghubungkan printer USB.';
toast.error(message);
}
}
async function handleConnectBluetooth() {
try {
await connectBluetooth();
open.value = false;
toast.success('Printer Bluetooth terhubung.');
} catch (error) {
const message = error instanceof Error
? error.message
: 'Gagal menghubungkan printer Bluetooth.';
toast.error(message);
}
}
function handleDisconnect() {
disconnect();
open.value = false;
toast.success('Printer terputus.');
}
</script>
<template>
<Popover v-model:open="open">
<PopoverTrigger as-child>
<Button variant="outline" class="shrink-0 gap-2 self-start sm:self-center">
<PlugZap class="size-4" />
Printer
<Badge
:variant="isConnected ? 'default' : 'secondary'"
class="rounded-full px-2 text-xs"
>
{{ isConnected ? connectionLabel : 'Offline' }}
</Badge>
</Button>
</PopoverTrigger>
<PopoverContent align="end" class="w-64 space-y-3 p-4">
<div class="space-y-1">
<p class="text-sm font-medium">
Koneksi Printer
</p>
<p class="text-muted-foreground text-xs">
Hubungkan printer thermal sebelum mencetak struk.
</p>
</div>
<div v-if="isConnected" class="rounded-md border bg-muted/40 px-3 py-2 text-sm">
Terhubung via <strong>{{ connectionLabel }}</strong>
</div>
<div class="grid gap-2">
<Button
variant="outline"
class="justify-start gap-2"
:disabled="!supportsUsb || connecting"
@click="handleConnectUsb"
>
<Usb class="size-4" />
{{ isConnected && connectionLabel === 'USB' ? 'Hubungkan ulang USB' : 'Hubungkan USB' }}
</Button>
<Button
variant="outline"
class="justify-start gap-2"
:disabled="!supportsBluetooth || connecting"
@click="handleConnectBluetooth"
>
<Bluetooth class="size-4" />
{{ isConnected && connectionLabel === 'Bluetooth' ? 'Hubungkan ulang Bluetooth' : 'Hubungkan Bluetooth' }}
</Button>
</div>
<Button
v-if="isConnected"
variant="ghost"
size="sm"
class="w-full"
:disabled="connecting"
@click="handleDisconnect"
>
Putuskan koneksi
</Button>
</PopoverContent>
</Popover>
</template>