105 lines
3.0 KiB
TypeScript
105 lines
3.0 KiB
TypeScript
import { computed, ref } from 'vue';
|
|
import { encodeOrderReceipt } from '@/lib/thermal-printer/encode-order-receipt';
|
|
import { normalizeEncoderOptions } from '@/lib/thermal-printer/normalize-encoder-options';
|
|
import {
|
|
connectBluetooth,
|
|
connectionState,
|
|
connectUsb,
|
|
disconnect as disconnectTransport,
|
|
getBluetoothEncoderSettings,
|
|
isWebBluetoothSupported,
|
|
isWebSerialSupported,
|
|
restoreConnection,
|
|
sendPrintData,
|
|
tryReconnect as tryReconnectTransport,
|
|
} from '@/lib/thermal-printer/stable-transport';
|
|
import type { PaperSize } from '@/lib/thermal-printer/types';
|
|
import type { OrderListItem } from '@/types/order';
|
|
|
|
const connecting = ref(false);
|
|
|
|
async function withConnecting<T>(callback: () => Promise<T>): Promise<T> {
|
|
connecting.value = true;
|
|
|
|
try {
|
|
return await callback();
|
|
} finally {
|
|
connecting.value = false;
|
|
}
|
|
}
|
|
|
|
export type PrintOrderReceiptOptions = {
|
|
order: OrderListItem;
|
|
paperSize: PaperSize;
|
|
storeName: string;
|
|
storeAddress: string;
|
|
};
|
|
|
|
async function printOrderReceipt(options: PrintOrderReceiptOptions): Promise<void> {
|
|
const { order, paperSize, storeName, storeAddress } = options;
|
|
let connection = connectionState.value;
|
|
|
|
if (!connection) {
|
|
const restored = await restoreConnection();
|
|
connection = connectionState.value;
|
|
|
|
if (!restored || !connection) {
|
|
throw new Error('Printer belum terhubung. Hubungkan printer terlebih dahulu.');
|
|
}
|
|
}
|
|
|
|
const bluetoothSettings = connection === 'bluetooth'
|
|
? getBluetoothEncoderSettings()
|
|
: null;
|
|
const encoderOptions = normalizeEncoderOptions({
|
|
language: bluetoothSettings?.language,
|
|
codepageMapping: bluetoothSettings?.codepageMapping,
|
|
});
|
|
|
|
const encoded = encodeOrderReceipt(order, {
|
|
storeName,
|
|
storeAddress,
|
|
paperSize,
|
|
language: connection === 'bluetooth' ? encoderOptions.language : undefined,
|
|
codepageMapping: connection === 'bluetooth' ? encoderOptions.codepageMapping : undefined,
|
|
});
|
|
|
|
await sendPrintData(encoded);
|
|
}
|
|
|
|
export function useThermalPrinter() {
|
|
const isConnected = computed(() => connectionState.value !== null);
|
|
|
|
const connectionLabel = computed(() => {
|
|
const connection = connectionState.value;
|
|
|
|
if (connection === 'usb') {
|
|
return 'USB';
|
|
}
|
|
|
|
if (connection === 'bluetooth') {
|
|
return 'Bluetooth';
|
|
}
|
|
|
|
return null;
|
|
});
|
|
|
|
return {
|
|
activeConnection: connectionState,
|
|
isConnected,
|
|
connectionLabel,
|
|
connecting,
|
|
connectUsb: () => withConnecting(connectUsb),
|
|
connectBluetooth: () => withConnecting(connectBluetooth),
|
|
tryReconnect: () => withConnecting(tryReconnectTransport),
|
|
disconnect: disconnectTransport,
|
|
printOrderReceipt,
|
|
supportsUsb: isWebSerialSupported(),
|
|
supportsBluetooth: isWebBluetoothSupported(),
|
|
};
|
|
}
|
|
|
|
export function getPaperSizeLabel(paperSize: PaperSize): string {
|
|
return paperSize;
|
|
}
|