refactor(ui): Rediseño completo de UI con Nuxt UI 4

- Nuevo layout responsivo mobile-first con tabs inferiores
- Sidebar colapsable en desktop con cola de impresión
- Sistema de templates reutilizables con localStorage
- Soporte Dark/Light mode con UColorModeButton
- Composables usePrintQueue y useTemplates para estado global
- Componentes modulares: CommandBuilder, QuickActions, PrintQueue, QueueItem
- Navegación por tabs: Constructor | Cola | Templates
This commit is contained in:
2025-11-24 17:46:20 -06:00
parent f3c13b356b
commit 470ecef4f1
39 changed files with 16114 additions and 1856 deletions

62
server/utils/printer.ts Normal file
View File

@@ -0,0 +1,62 @@
// Utilidades para comunicación con impresoras Epson ePOS
import axios from 'axios'
import https from 'https'
export interface PrinterResponse {
status: number
headers: any
data: string
}
export function buildSoapEnvelope(inner: string): string {
return (
'<?xml version="1.0" encoding="utf-8"?>' +
'<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">' +
'<s:Body>' +
'<epos-print xmlns="http://www.epson-pos.com/schemas/2011/03/epos-print">' +
inner +
'</epos-print>' +
'</s:Body>' +
'</s:Envelope>'
)
}
export async function sendToPrinter(
xml: string,
printerHost: string,
printerDeviceId: string,
printerTimeoutMs: number
): Promise<PrinterResponse> {
const url = `https://${printerHost}/cgi-bin/epos/service.cgi?devid=${encodeURIComponent(printerDeviceId)}&timeout=${printerTimeoutMs}`
// Agente HTTPS que acepta certificados auto-firmados
const httpsAgent = new https.Agent({
rejectUnauthorized: false
})
const res = await axios.post(url, xml, {
headers: {
'Content-Type': 'text/xml; charset=utf-8'
},
httpsAgent,
timeout: printerTimeoutMs + 5000,
validateStatus: () => true, // Aceptar cualquier status code
})
return {
status: res.status,
headers: res.headers,
data: typeof res.data === 'string' ? res.data : String(res.data)
}
}
export function parsePrinterResponse(responseData: string): {
success: boolean
code: string
} {
const success = /success\s*=\s*"true"/.test(responseData)
const codeMatch = responseData.match(/code="([^"]*)"/)
const code = codeMatch ? codeMatch[1] : ''
return { success, code }
}