mejorar de UI
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s
This commit is contained in:
@@ -1,64 +1,92 @@
|
||||
<template>
|
||||
<UCard>
|
||||
<UCard class="bg-gradient-to-br from-white to-slate-50 dark:from-slate-900 dark:to-slate-950 shadow-lg">
|
||||
<template #header>
|
||||
<h3 class="text-lg font-semibold">
|
||||
{{ lote ? 'Editar Lote' : 'Nuevo Lote' }}
|
||||
</h3>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
|
||||
{{ lote ? 'Edición' : 'Creación' }} · Lote
|
||||
</p>
|
||||
<h3 class="text-xl font-semibold">
|
||||
{{ lote ? 'Editar Lote' : 'Nuevo Lote' }}
|
||||
</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Completa los campos para registrar el lote en la trazabilidad.
|
||||
</p>
|
||||
</div>
|
||||
<UBadge color="blue" variant="subtle">{{ lote ? 'Edición' : 'Nuevo' }}</UBadge>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<UForm :state="formState" @submit="handleSubmit" class="space-y-4">
|
||||
<UFormGroup label="Código" name="codigo" help="Opcional - Si no se especifica, se generará automáticamente">
|
||||
<UInput
|
||||
v-model="formState.codigo"
|
||||
placeholder="Ej: UVA-001, SEC-042"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UForm :state="formState" @submit="handleSubmit" class="space-y-6">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<UFormGroup label="Código" name="codigo" help="Opcional · Se generará si lo dejas vacío">
|
||||
<UInput
|
||||
v-model="formState.codigo"
|
||||
placeholder="Ej: UVA-001, SEC-042"
|
||||
icon="i-heroicons-hashtag"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Tipo" name="tipo" required>
|
||||
<USelect
|
||||
v-model="formState.tipo"
|
||||
:options="TIPOS_LOTE"
|
||||
placeholder="Selecciona un tipo"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup label="Tipo" name="tipo" required>
|
||||
<USelect
|
||||
v-model="formState.tipo"
|
||||
:options="TIPOS_LOTE"
|
||||
option-attribute="label"
|
||||
value-attribute="value"
|
||||
placeholder="Selecciona un tipo"
|
||||
searchable
|
||||
/>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
|
||||
<UFormGroup label="Cantidad (kg)" name="cantidad_kg">
|
||||
<UInput
|
||||
v-model.number="formState.cantidad_kg"
|
||||
type="number"
|
||||
step="0.01"
|
||||
placeholder="0.00"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<UFormGroup label="Cantidad (kg)" name="cantidad_kg">
|
||||
<UInput
|
||||
v-model.number="formState.cantidad_kg"
|
||||
type="number"
|
||||
step="0.01"
|
||||
placeholder="0.00"
|
||||
icon="i-heroicons-scale"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup label="Lugar ID" name="lugar_id" help="Opcional - ID del lugar donde se encuentra">
|
||||
<UInput
|
||||
v-model.number="formState.lugar_id"
|
||||
type="number"
|
||||
placeholder="1"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup label="Lugar ID" name="lugar_id" help="Opcional · ID de ubicación">
|
||||
<UInput
|
||||
v-model.number="formState.lugar_id"
|
||||
type="number"
|
||||
placeholder="1"
|
||||
icon="i-heroicons-map-pin"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
|
||||
<UFormGroup label="Información Adicional (JSON)" name="meta" help="Opcional - Datos adicionales en formato JSON">
|
||||
<UFormGroup label="Información adicional (JSON)" name="meta" help="Ej: { "humedad": 12.5, "notas": "café especial" }">
|
||||
<UTextarea
|
||||
v-model="metaText"
|
||||
placeholder='{"humedad": 12.5, "notas": "café especial"}'
|
||||
rows="3"
|
||||
rows="4"
|
||||
class="font-mono"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<div class="flex gap-2 justify-end">
|
||||
<UButton
|
||||
type="button"
|
||||
variant="outline"
|
||||
label="Cancelar"
|
||||
@click="$emit('cancel')"
|
||||
/>
|
||||
<UButton
|
||||
type="submit"
|
||||
:loading="loading"
|
||||
:label="lote ? 'Actualizar' : 'Crear'"
|
||||
/>
|
||||
<div class="flex flex-col md:flex-row md:items-center justify-between gap-3 pt-2">
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||
Los campos marcados como opcionales se pueden dejar vacíos.
|
||||
</p>
|
||||
<div class="flex gap-2 justify-end">
|
||||
<UButton
|
||||
type="button"
|
||||
variant="outline"
|
||||
label="Cancelar"
|
||||
@click="$emit('cancel')"
|
||||
/>
|
||||
<UButton
|
||||
type="submit"
|
||||
color="primary"
|
||||
:loading="loading"
|
||||
:label="lote ? 'Actualizar' : 'Crear'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</UForm>
|
||||
</UCard>
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
<div class="flex gap-2">
|
||||
<USelect
|
||||
v-model="filtroTipo"
|
||||
:options="[{ value: '', label: 'Todos los tipos' }, ...TIPOS_LOTE]"
|
||||
:options="selectOptions"
|
||||
option-attribute="label"
|
||||
value-attribute="value"
|
||||
searchable
|
||||
placeholder="Filtrar por tipo"
|
||||
class="w-64"
|
||||
/>
|
||||
@@ -118,6 +121,10 @@ console.log('🟢 LotesTable: useLotes() completado')
|
||||
const lotes = ref<Lote[]>([])
|
||||
const loading = ref(false)
|
||||
const filtroTipo = ref('')
|
||||
const selectOptions = computed(() => [
|
||||
{ value: '', label: 'Todos los tipos' },
|
||||
...TIPOS_LOTE,
|
||||
])
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
const columns: ColumnDef<Lote>[] = [
|
||||
|
||||
Reference in New Issue
Block a user