92 lines
2.7 KiB
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>
|