Files
printerCentral/app/components/constructor/CommandBuilder.vue
josedario87 470ecef4f1 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
2025-11-24 17:46:20 -06:00

188 lines
5.7 KiB
Vue

<script setup lang="ts">
const queue = usePrintQueue()
// Estado del formulario
const text = ref('')
const align = ref('')
const font = ref('')
const width = ref<number | undefined>()
const height = ref<number | undefined>()
const bold = ref(false)
const underline = ref(false)
const reverse = ref(false)
const smooth = ref(false)
const color = ref('')
const feedLines = ref<number | undefined>()
const cut = ref('')
// Opciones para selects
const alignOptions = [
{ label: '(sin cambio)', value: '' },
{ label: 'Izquierda', value: 'left' },
{ label: 'Centro', value: 'center' },
{ label: 'Derecha', value: 'right' }
]
const fontOptions = [
{ label: '(sin cambio)', value: '' },
{ label: 'Font A', value: 'font_a' },
{ label: 'Font B', value: 'font_b' },
{ label: 'Font C', value: 'font_c' },
{ label: 'Font D', value: 'font_d' },
{ label: 'Font E', value: 'font_e' },
{ label: 'Special A', value: 'special_a' },
{ label: 'Special B', value: 'special_b' }
]
const colorOptions = [
{ label: '(default)', value: '' },
{ label: 'Color 1', value: 'color_1' },
{ label: 'Color 2', value: 'color_2' },
{ label: 'Color 3', value: 'color_3' },
{ label: 'Color 4', value: 'color_4' }
]
const cutOptions = [
{ label: '(no cortar)', value: '' },
{ label: 'Sin feed', value: 'no_feed' },
{ label: 'Con feed', value: 'feed' },
{ label: 'Reservar', value: 'reserve' },
{ label: 'Full sin feed', value: 'no_feed_fullcut' },
{ label: 'Full con feed', value: 'feed_fullcut' },
{ label: 'Full reservar', value: 'reserve_fullcut' }
]
const formatSections = [
{ label: 'Alineación y Fuente', value: 'alignment', icon: 'i-heroicons-bars-3-bottom-left' },
{ label: 'Tamaño', value: 'size', icon: 'i-heroicons-arrows-pointing-out' },
{ label: 'Estilo', value: 'style', icon: 'i-heroicons-paint-brush' },
{ label: 'Acciones finales', value: 'actions', icon: 'i-heroicons-scissors' }
]
function resetForm() {
text.value = ''
align.value = ''
font.value = ''
width.value = undefined
height.value = undefined
bold.value = false
underline.value = false
reverse.value = false
smooth.value = false
color.value = ''
feedLines.value = undefined
cut.value = ''
}
function queueText() {
const ops: any[] = []
if (align.value) ops.push({ op: 'textAlign', align: align.value })
if (font.value) ops.push({ op: 'textFont', font: font.value })
if (width.value || height.value) {
ops.push({ op: 'textSize', width: width.value, height: height.value })
}
ops.push({
op: 'textStyle',
em: bold.value,
ul: underline.value,
reverse: reverse.value,
...(color.value ? { color: color.value } : {})
})
if (text.value) ops.push({ op: 'text', value: text.value })
if (feedLines.value != null && feedLines.value !== 0) {
ops.push({ op: 'feedLine', line: Number(feedLines.value) })
}
if (cut.value) ops.push({ op: 'cut', type: cut.value })
queue.addOperations(ops)
}
</script>
<template>
<UCard>
<template #header>
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
Constructor de Comandos
</h2>
<UButton
icon="i-heroicons-arrow-path"
variant="ghost"
size="sm"
@click="resetForm"
/>
</div>
</template>
<!-- Textarea principal -->
<UFormField label="Texto a imprimir" class="mb-4">
<UTextarea
v-model="text"
:rows="4"
autoresize
placeholder="Escribe el texto a imprimir..."
/>
</UFormField>
<!-- Controles de formato con Accordion -->
<UAccordion :items="formatSections" type="multiple">
<template #alignment>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3 p-3">
<UFormField label="Alineación">
<USelect v-model="align" :items="alignOptions" placeholder="Seleccionar" />
</UFormField>
<UFormField label="Fuente">
<USelect v-model="font" :items="fontOptions" placeholder="Seleccionar" />
</UFormField>
<UFormField label="Color">
<USelect v-model="color" :items="colorOptions" placeholder="Seleccionar" />
</UFormField>
</div>
</template>
<template #size>
<div class="grid grid-cols-2 gap-3 p-3">
<UFormField label="Ancho (1-8)">
<UInput v-model.number="width" type="number" :min="1" :max="8" placeholder="1" />
</UFormField>
<UFormField label="Alto (1-8)">
<UInput v-model.number="height" type="number" :min="1" :max="8" placeholder="1" />
</UFormField>
</div>
</template>
<template #style>
<div class="flex flex-wrap gap-4 p-3">
<UCheckbox v-model="bold" label="Negrita" />
<UCheckbox v-model="underline" label="Subrayado" />
<UCheckbox v-model="reverse" label="Invertido" />
<UCheckbox v-model="smooth" label="Suavizado" />
</div>
</template>
<template #actions>
<div class="grid grid-cols-2 gap-3 p-3">
<UFormField label="Líneas de feed">
<UInput v-model.number="feedLines" type="number" :min="0" :max="255" placeholder="0" />
</UFormField>
<UFormField label="Corte de papel">
<USelect v-model="cut" :items="cutOptions" placeholder="Seleccionar" />
</UFormField>
</div>
</template>
</UAccordion>
<template #footer>
<div class="flex gap-2">
<UButton color="primary" @click="queueText">
Agregar a cola
</UButton>
<UButton variant="ghost" @click="resetForm">
Limpiar formulario
</UButton>
</div>
</template>
</UCard>
</template>