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

92 lines
2.7 KiB
Vue

<script setup lang="ts">
import { usePage } from '@inertiajs/vue3';
import { Printer } from '@lucide/vue';
import { computed, ref } from 'vue';
import { toast } from 'vue-sonner';
import { Button } from '@/components/ui/button';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { useThermalPrinter, getPaperSizeLabel } from '@/composables/useThermalPrinter';
import type { PaperSize } from '@/lib/thermal-printer/types';
import type { OrderListItem } from '@/types/order';
const props = defineProps<{
order: OrderListItem;
}>();
const page = usePage();
const open = ref(false);
const processing = ref(false);
const { isConnected, printOrderReceipt, tryReconnect } = useThermalPrinter();
const storeName = computed(() => page.props.name);
const storeAddress = computed(() => page.props.address);
const paperSizes: PaperSize[] = ['58mm', '80mm'];
async function handlePrint(paperSize: PaperSize) {
if (processing.value) {
return;
}
if (!isConnected.value) {
const restored = await tryReconnect();
if (!restored) {
toast.error('Printer belum terhubung. Hubungkan printer terlebih dahulu.');
return;
}
}
open.value = false;
processing.value = true;
try {
await printOrderReceipt({
order: props.order,
paperSize,
storeName: storeName.value,
storeAddress: storeAddress.value ?? '',
});
toast.success(`Struk ${props.order.order_number} dikirim ke printer ${getPaperSizeLabel(paperSize)}.`);
} catch (error) {
const message = error instanceof Error
? error.message
: 'Gagal mencetak struk pesanan.';
toast.error(message);
} finally {
processing.value = false;
}
}
</script>
<template>
<Popover v-model:open="open">
<PopoverTrigger as-child>
<Button variant="ghost" size="icon" class="size-8" :disabled="processing" title="Cetak struk">
<Printer class="size-4" />
<span class="sr-only">Cetak struk</span>
</Button>
</PopoverTrigger>
<PopoverContent align="end" class="w-40 space-y-2 p-3">
<p class="text-sm font-medium">
Ukuran kertas
</p>
<div class="grid grid-cols-2 gap-2">
<Button v-for="paperSize in paperSizes" :key="paperSize" variant="outline" size="sm" class="h-8"
:disabled="processing" @click="handlePrint(paperSize)">
{{ paperSize }}
</Button>
</div>
</PopoverContent>
</Popover>
</template>