Files
analiticaNucleo/nuxt4-app/app/components/empleados/DetalleTareas.vue
josedario87 f952aee0f5
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 54s
veamos
2025-11-13 18:11:11 -06:00

227 lines
7.6 KiB
Vue

<template>
<UCard class="brand-card border border-transparent">
<template #header>
<div class="flex items-center justify-between">
<h2 class="text-xl font-bold brand-section-title">Detalle de Tareas</h2>
<div class="flex items-center gap-2">
<UBadge color="gray" variant="soft" size="sm">
{{ data.length }} tareas
</UBadge>
<UButton
size="xs"
color="gray"
variant="soft"
icon="i-lucide-copy"
@click="copiarTexto"
>
Copiar Texto
</UButton>
<UButton
size="xs"
color="gray"
variant="soft"
icon="i-lucide-braces"
@click="copiarJSON"
>
Copiar JSON
</UButton>
</div>
</div>
</template>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-[var(--brand-border)]">
<th class="text-left py-3 px-3 font-semibold text-[var(--brand-text)]">Empleado</th>
<th class="text-left py-3 px-3 font-semibold text-[var(--brand-text)]">Tarea</th>
<th class="text-left py-3 px-3 font-semibold text-[var(--brand-text)]">Planilla</th>
<th class="text-right py-3 px-3 font-semibold text-[var(--brand-text)]">Precio</th>
<th class="text-center py-3 px-3 font-semibold text-[var(--brand-text)]">Tipo</th>
<th class="text-center py-3 px-3 font-semibold text-[var(--brand-text)]">Fecha</th>
<th class="text-center py-3 px-3 font-semibold text-[var(--brand-text)]">Estado</th>
<th class="text-left py-3 px-3 font-semibold text-[var(--brand-text)]">Observación</th>
</tr>
</thead>
<tbody>
<tr
v-for="tarea in data"
:key="tarea.tarea_id"
class="border-b border-[var(--brand-border)] hover:bg-[var(--brand-surface)] transition-colors"
>
<td class="py-3 px-3">
<div class="text-[var(--brand-text)] font-medium">{{ tarea.empleado_nombre }}</div>
<div class="text-[var(--brand-text-muted)] text-xs font-mono">{{ tarea.empleado_cedula || 'N/A' }}</div>
</td>
<td class="py-3 px-3 text-[var(--brand-text)]">
<span class="font-medium">{{ tarea.tarea_titulo }}</span>
</td>
<td class="py-3 px-3">
<div v-if="tarea.planilla_titulo" class="text-[var(--brand-text)] text-xs">
{{ tarea.planilla_titulo }}
</div>
<div v-else class="text-[var(--brand-text-muted)] text-xs italic">
Sin planilla
</div>
</td>
<td class="py-3 px-3 text-right">
<span class="font-mono font-bold text-blue-400">
{{ formatCurrency(tarea.tarea_precio || 0) }}
</span>
</td>
<td class="py-3 px-3 text-center">
<UBadge
:color="getTipoColor(tarea.tarea_tipo)"
variant="soft"
size="xs"
>
{{ tarea.tarea_tipo || 'general' }}
</UBadge>
</td>
<td class="py-3 px-3 text-center text-xs text-[var(--brand-text-muted)]">
{{ formatDate(tarea.tarea_fecha) }}
</td>
<td class="py-3 px-3 text-center">
<UBadge
:color="getEstadoColor(tarea.tarea_estado)"
variant="soft"
size="xs"
>
{{ tarea.tarea_estado || 'realizada' }}
</UBadge>
</td>
<td class="py-3 px-3 text-[var(--brand-text-muted)] text-xs max-w-xs truncate">
{{ tarea.tarea_observacion || '-' }}
</td>
</tr>
</tbody>
<tfoot v-if="data.length > 0" class="border-t-2 border-[var(--brand-border)]">
<tr class="bg-[var(--brand-surface)]">
<td colspan="3" class="py-3 px-3 font-semibold text-[var(--brand-text)]">
TOTALES ({{ data.length }} tareas)
</td>
<td class="py-3 px-3 text-right">
<span class="font-mono font-bold text-blue-400">
{{ formatCurrency(totalPrecios) }}
</span>
</td>
<td colspan="4"></td>
</tr>
</tfoot>
</table>
<div v-if="data.length === 0" class="text-center py-12 text-[var(--brand-text-muted)]">
<div class="i-lucide-inbox text-4xl mx-auto mb-3 opacity-50"></div>
<p>No hay tareas en el rango de fechas seleccionado</p>
</div>
</div>
</UCard>
</template>
<script setup lang="ts">
interface Tarea {
tarea_id: number
empleado_id: number
empleado_nombre: string
empleado_cedula: string
planilla_id: number | null
planilla_titulo: string | null
tarea_titulo: string
tarea_precio: number
tarea_tipo: string
tarea_estado: string
tarea_observacion: string | null
tarea_fecha: string
}
const props = defineProps<{
data: Tarea[]
rangoLegible: string
lastUpdated: string
}>()
// Computed para totales
const totalPrecios = computed(() => {
return props.data.reduce((sum, t) => sum + (t.tarea_precio || 0), 0)
})
// Funciones helper
const getTipoColor = (tipo: string) => {
const colores: Record<string, string> = {
'corte': 'purple',
'despulpe': 'orange',
'clasificacion': 'blue',
'secado': 'yellow',
'empaque': 'green',
'general': 'gray'
}
return colores[tipo?.toLowerCase()] || 'gray'
}
const getEstadoColor = (estado: string) => {
const colores: Record<string, string> = {
'realizada': 'green',
'pendiente': 'yellow',
'anulado': 'red',
'verificada': 'blue'
}
return colores[estado?.toLowerCase()] || 'green'
}
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('es-HN', {
style: 'currency',
currency: 'HNL',
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(value)
}
const formatDate = (dateString: string) => {
if (!dateString) return 'N/A'
const date = new Date(dateString)
return new Intl.DateTimeFormat('es-HN', {
year: 'numeric',
month: 'short',
day: 'numeric'
}).format(date)
}
async function copiarTexto() {
const footer = `
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 RESUMEN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📅 Rango: ${props.rangoLegible}
📋 Tareas: ${props.data.length}
🕐 Generado: ${props.lastUpdated}`
let texto = `📝 DETALLE DE TAREAS\n\n`
props.data.forEach((tarea, idx) => {
texto += `${idx + 1}. ${tarea.empleado_nombre} (${tarea.empleado_cedula || 'N/A'})\n`
texto += ` Tarea: ${tarea.tarea_titulo}\n`
texto += ` Precio: ${formatCurrency(tarea.tarea_precio || 0)}\n`
texto += ` Tipo: ${tarea.tarea_tipo || 'general'}\n`
texto += ` Fecha: ${formatDate(tarea.tarea_fecha)}\n`
texto += ` Planilla: ${tarea.planilla_titulo || 'Sin planilla'}\n`
texto += ` Estado: ${tarea.tarea_estado || 'realizada'}\n`
if (tarea.tarea_observacion) {
texto += ` Observación: ${tarea.tarea_observacion}\n`
}
texto += `\n`
})
texto += `\n💰 TOTAL PRECIOS: ${formatCurrency(totalPrecios.value)}${footer}`
await navigator.clipboard.writeText(texto)
alert('✅ Detalle de Tareas copiado al portapapeles')
}
async function copiarJSON() {
const json = JSON.stringify(props.data, null, 2)
await navigator.clipboard.writeText(json)
alert('✅ JSON copiado al portapapeles')
}
</script>