Feat: agregar creación de lotes de input en formulario de operación
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m6s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m6s
Ahora el formulario de crear operación permite crear nuevos lotes de entrada directamente desde el paso 2, sin necesidad de salir del modal. Cambios: - Agregar botón "Nuevo lote de entrada" en el paso 2 - Mostrar formulario inline para crear lote con código, tipo y cantidad - Al crear el lote, se agrega automáticamente a la lista de disponibles - Se selecciona automáticamente como input de la operación - Importar createLote del composable useLotes - Agregar estado showCreateInputForm y creatingInput - Implementar funciones cancelCreateInput y handleCreateInput Beneficios: - Flujo más ágil sin interrupciones - Consistencia con la creación de lotes de output - Mejor experiencia de usuario
This commit is contained in:
@@ -63,6 +63,7 @@
|
||||
</div>
|
||||
|
||||
<div v-else class="space-y-2">
|
||||
<!-- Lotes existentes -->
|
||||
<div
|
||||
v-for="lote in lotesDisponibles"
|
||||
:key="lote.id"
|
||||
@@ -90,8 +91,68 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Formulario para crear nuevo lote de entrada -->
|
||||
<div v-if="showCreateInputForm" class="p-4 border-2 border-dashed border-primary/50 rounded-lg space-y-3 bg-primary/5">
|
||||
<div class="flex justify-between items-center">
|
||||
<h5 class="font-medium text-primary">Nuevo lote de entrada</h5>
|
||||
<UButton
|
||||
icon="i-heroicons-x-mark"
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
@click="cancelCreateInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
<UFormGroup label="Código (opcional)">
|
||||
<UInput v-model="newInputLote.codigo" placeholder="Ej: UVA-001" icon="i-heroicons-hashtag" />
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Tipo" required>
|
||||
<USelect
|
||||
v-model="newInputLote.tipo"
|
||||
:items="TIPOS_LOTE"
|
||||
label-key="label"
|
||||
value-key="value"
|
||||
placeholder="Selecciona tipo"
|
||||
searchable
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Cantidad (kg)">
|
||||
<UInput v-model.number="newInputLote.cantidad_kg" type="number" step="0.01" placeholder="0.00" icon="i-heroicons-scale" />
|
||||
</UFormGroup>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 justify-end">
|
||||
<UButton
|
||||
label="Cancelar"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@click="cancelCreateInput"
|
||||
/>
|
||||
<UButton
|
||||
label="Crear y Seleccionar"
|
||||
color="primary"
|
||||
size="sm"
|
||||
:loading="creatingInput"
|
||||
:disabled="!newInputLote.tipo"
|
||||
@click="handleCreateInput"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UButton
|
||||
v-if="!showCreateInputForm"
|
||||
icon="i-heroicons-plus"
|
||||
label="Nuevo lote de entrada"
|
||||
variant="outline"
|
||||
block
|
||||
@click="showCreateInputForm = true"
|
||||
/>
|
||||
|
||||
<div class="flex gap-2 justify-end pt-4">
|
||||
<UButton
|
||||
label="Anterior"
|
||||
@@ -191,12 +252,19 @@ const emit = defineEmits<{
|
||||
success: []
|
||||
}>()
|
||||
|
||||
const { fetchLotes, createOperacion, TIPOS_OPERACION, TIPOS_LOTE } = useLotes()
|
||||
const { fetchLotes, createLote, createOperacion, TIPOS_OPERACION, TIPOS_LOTE } = useLotes()
|
||||
|
||||
const step = ref(1)
|
||||
const loading = ref(false)
|
||||
const loadingLotes = ref(false)
|
||||
const lotesDisponibles = ref<Lote[]>([])
|
||||
const showCreateInputForm = ref(false)
|
||||
const creatingInput = ref(false)
|
||||
const newInputLote = ref({
|
||||
codigo: '',
|
||||
tipo: '',
|
||||
cantidad_kg: undefined as number | undefined,
|
||||
})
|
||||
|
||||
const formState = ref({
|
||||
tipo: '',
|
||||
@@ -247,6 +315,43 @@ const removeOutput = (index: number) => {
|
||||
formState.value.outputs.splice(index, 1)
|
||||
}
|
||||
|
||||
const cancelCreateInput = () => {
|
||||
showCreateInputForm.value = false
|
||||
newInputLote.value = {
|
||||
codigo: '',
|
||||
tipo: '',
|
||||
cantidad_kg: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
const handleCreateInput = async () => {
|
||||
creatingInput.value = true
|
||||
try {
|
||||
const createdLote = await createLote({
|
||||
codigo: newInputLote.value.codigo || undefined,
|
||||
tipo: newInputLote.value.tipo,
|
||||
cantidad_kg: newInputLote.value.cantidad_kg,
|
||||
})
|
||||
|
||||
if (createdLote) {
|
||||
// Agregar a la lista de lotes disponibles
|
||||
lotesDisponibles.value.unshift(createdLote)
|
||||
|
||||
// Seleccionarlo automáticamente como input
|
||||
formState.value.inputs.push({
|
||||
lote_id: createdLote.id,
|
||||
cantidad_kg: createdLote.cantidad_kg || undefined,
|
||||
_lote: createdLote,
|
||||
})
|
||||
|
||||
// Cerrar el formulario
|
||||
cancelCreateInput()
|
||||
}
|
||||
} finally {
|
||||
creatingInput.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const getTipoLabel = (tipo: string) => {
|
||||
const foundOp = TIPOS_OPERACION.find((t) => t.value === tipo)
|
||||
if (foundOp) return foundOp.label
|
||||
|
||||
Reference in New Issue
Block a user