diff --git a/resources/js/pages/admin/manage/order/hooks/use-order-print.ts b/resources/js/pages/admin/manage/order/hooks/use-order-print.ts new file mode 100644 index 0000000..a8ccf0f --- /dev/null +++ b/resources/js/pages/admin/manage/order/hooks/use-order-print.ts @@ -0,0 +1,97 @@ +import { usePrinter } from '@/hooks/use-printer'; +import { EscPosEncoder } from '@/lib/esc-pos-encoder'; +import type { Order } from '@/types/order'; +import { format } from 'date-fns'; +import { id } from 'date-fns/locale'; +import { useCallback } from 'react'; +import { toast } from 'sonner'; + +export function useOrderPrint() { + const { + isConnected, + name, + connectBluetooth, + connectUsb, + disconnect, + sendData, + paperSize, + setPaperSize + } = usePrinter(); + + const handlePrint = useCallback(async (order: Order) => { + if (!isConnected) { + toast.error('Hubungkan printer terlebih dahulu'); + + return; + } + + const width = paperSize === '58' ? 32 : 48; + const line = '-'.repeat(width); + + const encoder = new EscPosEncoder(); + const result = encoder + .initialize() + .align(1) + .size(1) + .bold(true) + .line('VN Grup') + .size(0) + .bold(false) + .line(line) + .align(0) + .line(`No. Invoice : ${order.invoice_number}`) + .line(`Tanggal : ${format(new Date(order.created_at), 'dd MMMM yyyy HH:mm', { locale: id })}`) + .line(`Pelanggan : ${order.customer_name}`) + .line(line); + + order.items?.forEach((item, index) => { + if (index > 0) { + result.line(); + } + + result.line(item.product?.name || 'Produk'); + const qtyPrice = `${item.qty} x ${item.price_formatted}`; + const subtotal = item.total_formatted; + const spaces = width - qtyPrice.length - subtotal.length; + result.line(qtyPrice + ' '.repeat(Math.max(0, spaces)) + subtotal); + }); + + result.line(line); + + const discountAmount = Number(order.discount || 0); + + if (discountAmount > 0) { + const discountLabel = 'Diskon:'; + const discountVal = `- Rp ${discountAmount.toLocaleString('id-ID')}`; + const dSpaces = width - discountLabel.length - discountVal.length; + result.line(discountLabel + ' '.repeat(Math.max(0, dSpaces)) + discountVal); + } + + const totalLabel = 'TOTAL:'; + const totalVal = order.total_formatted; + const tSpaces = width - totalLabel.length - totalVal.length; + result.bold(true).line(totalLabel + ' '.repeat(Math.max(0, tSpaces)) + totalVal).bold(false); + + result + .line(line) + .align(1) + .feed(1) + .line('Terima Kasih') + .line('Selamat Belanja Kembali') + .feed(1) + .cut(); + + await sendData(result.encode()); + }, [isConnected, sendData, paperSize]); + + return { + isConnected, + name, + paperSize, + connectBluetooth, + connectUsb, + disconnect, + setPaperSize, + handlePrint + }; +} diff --git a/resources/js/pages/admin/manage/order/index.tsx b/resources/js/pages/admin/manage/order/index.tsx index df29c48..510ea83 100644 --- a/resources/js/pages/admin/manage/order/index.tsx +++ b/resources/js/pages/admin/manage/order/index.tsx @@ -1,33 +1,16 @@ -import { Head, Link } from '@inertiajs/react'; -import { format } from 'date-fns'; -import { id } from 'date-fns/locale'; -import { Bluetooth, Plus, Printer, Trash2, Unplug, Usb } from 'lucide-react'; -import { useCallback } from 'react'; -import { toast } from 'sonner'; import { DataTable } from '@/components/data-table'; import { DeleteConfirmation } from '@/components/modal/delete-confirmation'; import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuRadioGroup, - DropdownMenuRadioItem, - DropdownMenuSeparator, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; +import { Head, Link } from '@inertiajs/react'; +import { Plus, Trash2 } from 'lucide-react'; -import { usePrinter } from '@/hooks/use-printer'; -import { EscPosEncoder } from '@/lib/esc-pos-encoder'; import * as orderRoutes from '@/routes/order'; import type { Order } from '@/types/order'; import { useOrderIndex } from './hooks/use-order-index'; +import { useOrderPrint } from './hooks/use-order-print'; import { getColumns } from './partials/columns'; +import { PrinterSettings } from './partials/printer-settings'; export default function OrderIndex({ orders }: { orders: Order[] }) { const { @@ -48,79 +31,13 @@ export default function OrderIndex({ orders }: { orders: Order[] }) { const { isConnected, name, + paperSize, connectBluetooth, connectUsb, disconnect, - sendData, - paperSize, - setPaperSize - } = usePrinter(); - - const handlePrint = useCallback(async (order: Order) => { - if (!isConnected) { - toast.error('Hubungkan printer terlebih dahulu'); - - return; - } - - const width = paperSize === '58' ? 32 : 48; - const line = '-'.repeat(width); - - const encoder = new EscPosEncoder(); - const result = encoder - .initialize() - .align(1) - .size(1) - .bold(true) - .line('VN Grup') - .size(0) - .bold(false) - .line(line) - .align(0) - .line(`No. Invoice : ${order.invoice_number}`) - .line(`Tanggal : ${format(new Date(order.created_at), 'dd MMMM yyyy HH:mm', { locale: id })}`) - .line(`Pelanggan : ${order.customer_name}`) - .line(line); - - order.items?.forEach((item, index) => { - if (index > 0) { -result.line(); -} - - result.line(item.product?.name || 'Produk'); - const qtyPrice = `${item.qty} x ${item.price_formatted}`; - const subtotal = item.total_formatted; - const spaces = width - qtyPrice.length - subtotal.length; - result.line(qtyPrice + ' '.repeat(Math.max(0, spaces)) + subtotal); - }); - - result.line(line); - - const discountAmount = Number(order.discount || 0); - - if (discountAmount > 0) { - const discountLabel = 'Diskon:'; - const discountVal = `- Rp ${discountAmount.toLocaleString('id-ID')}`; - const dSpaces = width - discountLabel.length - discountVal.length; - result.line(discountLabel + ' '.repeat(Math.max(0, dSpaces)) + discountVal); - } - - const totalLabel = 'TOTAL:'; - const totalVal = order.total_formatted; - const tSpaces = width - totalLabel.length - totalVal.length; - result.bold(true).line(totalLabel + ' '.repeat(Math.max(0, tSpaces)) + totalVal).bold(false); - - result - .line(line) - .align(1) - .feed(1) - .line('Terima Kasih') - .line('Selamat Belanja Kembali') - .feed(1) - .cut(); - - await sendData(result.encode()); - }, [isConnected, sendData, paperSize]); + setPaperSize, + handlePrint + } = useOrderPrint(); const columns = getColumns({ onDelete, onPrint: handlePrint }); @@ -133,50 +50,15 @@ result.line();