mejoras UX exquisitas

This commit is contained in:
2025-10-01 00:15:06 -06:00
parent 47e42ec985
commit b8d0c67659
4 changed files with 529 additions and 9 deletions

View File

@@ -54,8 +54,24 @@ const data = computed<(IngresoWithChildren | ClienteWithChildren)[]>(() => {
// Clientes as parent, ingresos as children
const clientesData = props.clientes.map(cliente => {
const clienteIngresos = props.ingresos.filter(i => i.cliente_id === cliente.id)
// Agregar campos agregados al cliente
const peso_seco = clienteIngresos.reduce((sum, i) => sum + (i.peso_seco || 0), 0)
const peso_neto = clienteIngresos.reduce((sum, i) => sum + (i.peso_neto || 0), 0)
// Precio promedio ponderado (por peso_neto)
const totalPrecioXPeso = clienteIngresos.reduce((sum, i) => sum + (i.precio * i.peso_neto), 0)
const precio = peso_neto > 0 ? totalPrecioXPeso / peso_neto : 0
// Estados únicos
const estados = [...new Set(clienteIngresos.map(i => i.estado))]
return {
...cliente,
peso_seco,
peso_neto,
precio,
estado: estados.length > 0 ? estados.join(', ') : '',
children: clienteIngresos
}
})
@@ -164,6 +180,14 @@ const columns: TableColumn<IngresoWithChildren | ClienteWithChildren>[] = [
cell: ({ row }) => {
const original = row.original as any
const isIngreso = 'tipo' in original
const isCliente = 'name' in original && !('tipo' in original)
// Si es cliente parent con peso_seco agregado, mostrarlo
if (isCliente && row.depth === 0 && original.peso_seco !== undefined) {
const peso = Number.parseFloat(original.peso_seco || 0)
return h('div', { class: 'text-right font-medium text-yellow-500' }, peso.toFixed(2))
}
if (!isIngreso) return h('div', { class: 'text-right text-gray-500' }, '—')
const peso = Number.parseFloat(row.getValue('peso_seco') || 0)
@@ -176,6 +200,14 @@ const columns: TableColumn<IngresoWithChildren | ClienteWithChildren>[] = [
cell: ({ row }) => {
const original = row.original as any
const isIngreso = 'tipo' in original
const isCliente = 'name' in original && !('tipo' in original)
// Si es cliente parent con peso_neto agregado, mostrarlo
if (isCliente && row.depth === 0 && original.peso_neto !== undefined) {
const peso = Number.parseFloat(original.peso_neto || 0)
return h('div', { class: 'text-right font-medium text-yellow-500' }, peso.toFixed(2))
}
if (!isIngreso) return h('div', { class: 'text-right text-gray-500' }, '—')
const peso = Number.parseFloat(row.getValue('peso_neto') || 0)
@@ -188,6 +220,21 @@ const columns: TableColumn<IngresoWithChildren | ClienteWithChildren>[] = [
cell: ({ row }) => {
const original = row.original as any
const isIngreso = 'tipo' in original
const isCliente = 'name' in original && !('tipo' in original)
// Si es cliente parent con precio agregado, mostrarlo
if (isCliente && row.depth === 0 && original.precio !== undefined) {
const precio = Number.parseFloat(original.precio || 0)
const formatted = new Intl.NumberFormat('es-HN', {
style: 'currency',
currency: 'HNL',
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(precio).replace('HNL', 'L')
return h('div', { class: 'text-right font-medium text-yellow-500' }, formatted)
}
if (!isIngreso) return h('div', { class: 'text-right text-gray-500' }, '—')
const precio = Number.parseFloat(row.getValue('precio') || 0)
@@ -210,7 +257,22 @@ const columns: TableColumn<IngresoWithChildren | ClienteWithChildren>[] = [
const isIngreso = 'tipo' in original
if (isCliente) {
// Cliente row - show if empleado
// Cliente row (parent) - show aggregated estados
const isParent = row.depth === 0
if (isParent && original.estado) {
// Si tiene campo estado agregado, mostrarlo como badges múltiples
const estados = original.estado.split(', ')
return h('div', { class: 'flex flex-wrap gap-1' }, estados.map((estado: string) =>
h('span', {
class: estado === 'pagado'
? 'inline-flex items-center gap-1 px-2 py-0.5 rounded bg-green-500/20 text-green-300 border border-green-400/30 text-xs'
: 'inline-flex items-center gap-1 px-2 py-0.5 rounded bg-yellow-500/20 text-yellow-300 border border-yellow-400/30 text-xs'
}, estado === 'pagado' ? '✓ Pagado' : '⏳ Pendiente')
))
}
// Cliente row (child) - show if empleado
return original.empleado
? h('span', { class: 'inline-flex items-center gap-1 px-2 py-0.5 rounded bg-blue-500/20 text-blue-300 border border-blue-400/30 text-xs' }, [
h('span', '💼'),