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>
|
||||||
|
|
||||||
<div v-else class="space-y-2">
|
<div v-else class="space-y-2">
|
||||||
|
<!-- Lotes existentes -->
|
||||||
<div
|
<div
|
||||||
v-for="lote in lotesDisponibles"
|
v-for="lote in lotesDisponibles"
|
||||||
:key="lote.id"
|
:key="lote.id"
|
||||||
@@ -90,8 +91,68 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</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">
|
<div class="flex gap-2 justify-end pt-4">
|
||||||
<UButton
|
<UButton
|
||||||
label="Anterior"
|
label="Anterior"
|
||||||
@@ -191,12 +252,19 @@ const emit = defineEmits<{
|
|||||||
success: []
|
success: []
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { fetchLotes, createOperacion, TIPOS_OPERACION, TIPOS_LOTE } = useLotes()
|
const { fetchLotes, createLote, createOperacion, TIPOS_OPERACION, TIPOS_LOTE } = useLotes()
|
||||||
|
|
||||||
const step = ref(1)
|
const step = ref(1)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const loadingLotes = ref(false)
|
const loadingLotes = ref(false)
|
||||||
const lotesDisponibles = ref<Lote[]>([])
|
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({
|
const formState = ref({
|
||||||
tipo: '',
|
tipo: '',
|
||||||
@@ -247,6 +315,43 @@ const removeOutput = (index: number) => {
|
|||||||
formState.value.outputs.splice(index, 1)
|
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 getTipoLabel = (tipo: string) => {
|
||||||
const foundOp = TIPOS_OPERACION.find((t) => t.value === tipo)
|
const foundOp = TIPOS_OPERACION.find((t) => t.value === tipo)
|
||||||
if (foundOp) return foundOp.label
|
if (foundOp) return foundOp.label
|
||||||
|
|||||||
Reference in New Issue
Block a user