All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 53s
- Mover TotalesMonetariosComercio a components/comercios/ - Mover TotalesPesoComercio a components/comercios/ - Mover TablaComerciosResumen a components/comercios/ - Actualizar referencias en informe-comercios.vue con prefijos de carpeta
238 lines
10 KiB
Vue
238 lines
10 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">Totales de Peso</h2>
|
|
<div class="flex items-center gap-2">
|
|
<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="space-y-6">
|
|
<!-- Totales por Tipo de Café -->
|
|
<div>
|
|
<h3 class="text-lg font-semibold text-[var(--brand-primary)] mb-3">Quintales Seco por Tipo</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-5 gap-3">
|
|
<!-- Uva -->
|
|
<div class="rounded-lg border border-[var(--brand-border)] px-4 py-3"
|
|
style="background: linear-gradient(135deg, var(--brand-surface) 0%, rgba(139, 69, 19, 0.1) 100%);">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<div class="w-3 h-3 rounded-full" style="background-color: var(--coffee-uva, #8B4513);"></div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] uppercase tracking-wide">Uva</div>
|
|
</div>
|
|
<div class="text-2xl font-bold text-[var(--brand-text)]">
|
|
{{ formatNumber(data.qq_seco_uva) }}
|
|
</div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] mt-1">
|
|
QQ Seco
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mojado -->
|
|
<div class="rounded-lg border border-[var(--brand-border)] px-4 py-3"
|
|
style="background: linear-gradient(135deg, var(--brand-surface) 0%, rgba(30, 144, 255, 0.1) 100%);">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<div class="w-3 h-3 rounded-full" style="background-color: var(--coffee-mojado, #1E90FF);"></div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] uppercase tracking-wide">Mojado</div>
|
|
</div>
|
|
<div class="text-2xl font-bold text-[var(--brand-text)]">
|
|
{{ formatNumber(data.qq_seco_mojado) }}
|
|
</div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] mt-1">
|
|
QQ Seco
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Oreado -->
|
|
<div class="rounded-lg border border-[var(--brand-border)] px-4 py-3"
|
|
style="background: linear-gradient(135deg, var(--brand-surface) 0%, rgba(255, 140, 0, 0.1) 100%);">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<div class="w-3 h-3 rounded-full" style="background-color: var(--coffee-oreado, #FF8C00);"></div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] uppercase tracking-wide">Oreado</div>
|
|
</div>
|
|
<div class="text-2xl font-bold text-[var(--brand-text)]">
|
|
{{ formatNumber(data.qq_seco_oreado) }}
|
|
</div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] mt-1">
|
|
QQ Seco
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Verde -->
|
|
<div class="rounded-lg border border-[var(--brand-border)] px-4 py-3"
|
|
style="background: linear-gradient(135deg, var(--brand-surface) 0%, rgba(34, 139, 34, 0.1) 100%);">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<div class="w-3 h-3 rounded-full" style="background-color: var(--coffee-verde, #228B22);"></div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] uppercase tracking-wide">Verde</div>
|
|
</div>
|
|
<div class="text-2xl font-bold text-[var(--brand-text)]">
|
|
{{ formatNumber(data.qq_verde) }}
|
|
</div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] mt-1">
|
|
QQ
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Total -->
|
|
<div class="rounded-lg border-2 border-[var(--brand-primary)] bg-[var(--brand-surface)] px-4 py-3">
|
|
<div class="text-xs text-[var(--brand-text-muted)] uppercase tracking-wide mb-2">Total</div>
|
|
<div class="text-2xl font-bold text-[var(--brand-primary)]">
|
|
{{ formatNumber(data.total_qq_seco) }}
|
|
</div>
|
|
<div class="text-xs text-[var(--brand-text-muted)] mt-1">
|
|
QQ Seco
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Visualización de Distribución por Tipo -->
|
|
<div v-if="showChart" class="mt-6">
|
|
<h4 class="text-sm font-semibold text-[var(--brand-text)] mb-3">Distribución de Peso por Tipo</h4>
|
|
<div class="space-y-2">
|
|
<div class="flex items-center gap-3">
|
|
<span class="text-xs w-20 text-[var(--brand-text-muted)]">Uva</span>
|
|
<div class="flex-1 h-8 bg-[var(--brand-surface)] rounded-lg overflow-hidden border border-[var(--brand-border)]">
|
|
<div
|
|
class="h-full flex items-center justify-end px-2 transition-all duration-500"
|
|
style="background-color: var(--coffee-uva, #8B4513);"
|
|
:style="{ width: `${calcularPorcentaje(data.qq_seco_uva)}%` }"
|
|
>
|
|
<span class="text-xs font-semibold text-white">{{ calcularPorcentaje(data.qq_seco_uva) }}%</span>
|
|
</div>
|
|
</div>
|
|
<span class="text-xs w-32 text-right text-[var(--brand-text)]">{{ formatNumber(data.qq_seco_uva) }} QQ</span>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-3">
|
|
<span class="text-xs w-20 text-[var(--brand-text-muted)]">Mojado</span>
|
|
<div class="flex-1 h-8 bg-[var(--brand-surface)] rounded-lg overflow-hidden border border-[var(--brand-border)]">
|
|
<div
|
|
class="h-full flex items-center justify-end px-2 transition-all duration-500"
|
|
style="background-color: var(--coffee-mojado, #1E90FF);"
|
|
:style="{ width: `${calcularPorcentaje(data.qq_seco_mojado)}%` }"
|
|
>
|
|
<span class="text-xs font-semibold text-white">{{ calcularPorcentaje(data.qq_seco_mojado) }}%</span>
|
|
</div>
|
|
</div>
|
|
<span class="text-xs w-32 text-right text-[var(--brand-text)]">{{ formatNumber(data.qq_seco_mojado) }} QQ</span>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-3">
|
|
<span class="text-xs w-20 text-[var(--brand-text-muted)]">Oreado</span>
|
|
<div class="flex-1 h-8 bg-[var(--brand-surface)] rounded-lg overflow-hidden border border-[var(--brand-border)]">
|
|
<div
|
|
class="h-full flex items-center justify-end px-2 transition-all duration-500"
|
|
style="background-color: var(--coffee-oreado, #FF8C00);"
|
|
:style="{ width: `${calcularPorcentaje(data.qq_seco_oreado)}%` }"
|
|
>
|
|
<span class="text-xs font-semibold text-white">{{ calcularPorcentaje(data.qq_seco_oreado) }}%</span>
|
|
</div>
|
|
</div>
|
|
<span class="text-xs w-32 text-right text-[var(--brand-text)]">{{ formatNumber(data.qq_seco_oreado) }} QQ</span>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-3">
|
|
<span class="text-xs w-20 text-[var(--brand-text-muted)]">Verde</span>
|
|
<div class="flex-1 h-8 bg-[var(--brand-surface)] rounded-lg overflow-hidden border border-[var(--brand-border)]">
|
|
<div
|
|
class="h-full flex items-center justify-end px-2 transition-all duration-500"
|
|
style="background-color: var(--coffee-verde, #228B22);"
|
|
:style="{ width: `${calcularPorcentaje(data.qq_verde)}%` }"
|
|
>
|
|
<span class="text-xs font-semibold text-white">{{ calcularPorcentaje(data.qq_verde) }}%</span>
|
|
</div>
|
|
</div>
|
|
<span class="text-xs w-32 text-right text-[var(--brand-text)]">{{ formatNumber(data.qq_verde) }} QQ</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</UCard>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const props = defineProps<{
|
|
data: {
|
|
qq_seco_uva: number
|
|
qq_seco_mojado: number
|
|
qq_seco_oreado: number
|
|
qq_verde: number
|
|
total_qq_seco: number
|
|
}
|
|
contadores?: {
|
|
total_comercios?: number
|
|
comercios_filtrados?: number
|
|
total_clientes?: number
|
|
clientes_con_comercios_filtrados?: number
|
|
}
|
|
rangoLegible: string
|
|
lastUpdated: string
|
|
}>()
|
|
|
|
const showChart = ref(true)
|
|
|
|
const formatNumber = (value: number) => {
|
|
if (!value) return '0.00'
|
|
return new Intl.NumberFormat('es-HN', {
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2
|
|
}).format(value)
|
|
}
|
|
|
|
const calcularPorcentaje = (parte: number): string => {
|
|
if (!props.data.total_qq_seco || props.data.total_qq_seco === 0) return '0.0'
|
|
const porcentaje = (parte / props.data.total_qq_seco) * 100
|
|
return porcentaje.toFixed(1)
|
|
}
|
|
|
|
async function copiarTexto() {
|
|
const footer = `
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
📊 RESUMEN
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
📅 Rango: ${props.rangoLegible}
|
|
📦 Comercios: ${props.contadores?.comercios_filtrados || 0} de ${props.contadores?.total_comercios || 0} registros
|
|
👥 Clientes: ${props.contadores?.clientes_con_comercios_filtrados || 0} de ${props.contadores?.total_clientes || 0} clientes
|
|
🕐 Generado: ${props.lastUpdated}`
|
|
|
|
const texto = `⚖️ TOTALES DE PESO POR TIPO
|
|
|
|
☕ QUINTALES SECO POR TIPO:
|
|
Uva: ${formatNumber(props.data.qq_seco_uva)} QQ (${calcularPorcentaje(props.data.qq_seco_uva)}%)
|
|
Mojado: ${formatNumber(props.data.qq_seco_mojado)} QQ (${calcularPorcentaje(props.data.qq_seco_mojado)}%)
|
|
Oreado: ${formatNumber(props.data.qq_seco_oreado)} QQ (${calcularPorcentaje(props.data.qq_seco_oreado)}%)
|
|
Verde: ${formatNumber(props.data.qq_verde)} QQ (${calcularPorcentaje(props.data.qq_verde)}%)
|
|
|
|
📊 TOTAL:
|
|
Total QQ Seco: ${formatNumber(props.data.total_qq_seco)} QQ${footer}`
|
|
|
|
await navigator.clipboard.writeText(texto)
|
|
alert('✅ Totales de Peso copiados al portapapeles')
|
|
}
|
|
|
|
async function copiarJSON() {
|
|
const json = JSON.stringify(props.data, null, 2)
|
|
await navigator.clipboard.writeText(json)
|
|
alert('✅ JSON copiado al portapapeles')
|
|
}
|
|
</script>
|