pagina panorama facturador en camino

This commit is contained in:
2025-09-30 03:22:18 -06:00
parent ce71689d66
commit b171fbdb21
13 changed files with 1047 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
<template>
<div
class="p-4 rounded-lg border transition-all"
:class="[variantClasses, props.class]"
>
<div class="flex flex-col">
<span class="text-xs uppercase tracking-wide opacity-80 mb-1">{{ label }}</span>
<div class="flex items-baseline gap-2">
<span class="text-2xl font-bold">{{ value }}</span>
<span v-if="unit" class="text-sm opacity-70">{{ unit }}</span>
</div>
<slot></slot>
</div>
</div>
</template>
<script setup lang="ts">
interface Props {
label: string
value: string | number
unit?: string
variant?: 'default' | 'primary' | 'success' | 'danger' | 'warning' | 'info'
class?: string
}
const props = withDefaults(defineProps<Props>(), {
variant: 'default'
})
const variantClasses = computed(() => {
const variants = {
default: 'bg-[#1c140c] border-[#3a2a16] text-[var(--brand-text)]',
primary: 'bg-[#1c140c] border-[#c08040] text-[var(--brand-primary)]',
success: 'bg-[#1c140c] border-green-600/30 text-green-400',
danger: 'bg-[#1c140c] border-red-600/30 text-red-400',
warning: 'bg-[#1c140c] border-yellow-600/30 text-yellow-400',
info: 'bg-[#1c140c] border-cyan-600/30 text-cyan-400'
}
return variants[props.variant]
})
</script>

View File

@@ -0,0 +1,42 @@
<template>
<UCard class="brand-card border border-transparent">
<template #header>
<h2 class="text-xl font-bold brand-section-title">Inventarios en Depósito</h2>
</template>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<MetricCard
label="Total QQ Seco en Depósito"
:value="metrics.totalQqSecoDeposito.value.toFixed(2)"
unit="QQ"
variant="warning"
/>
<MetricCard
label="Total QQ Mojado en Depósito"
:value="metrics.totalQqMojadoDeposito.value.toFixed(2)"
unit="QQ"
variant="info"
/>
<MetricCard
label="Total QQ Oreado en Depósito"
:value="metrics.totalQqOreadoDeposito.value.toFixed(2)"
unit="QQ"
variant="info"
/>
<MetricCard
label="Total Lb Uva en Depósito"
:value="metrics.totalLbUvaDeposito.value.toFixed(2)"
unit="lb"
variant="info"
/>
</div>
</UCard>
</template>
<script setup lang="ts">
import type { IngresosMetrics } from '~/composables/useIngresosMetrics'
defineProps<{
metrics: IngresosMetrics
}>()
</script>

View File

@@ -0,0 +1,46 @@
<template>
<UCard class="brand-card border border-transparent">
<template #header>
<h2 class="text-xl font-bold brand-section-title">Inversión Restante a Realizar</h2>
</template>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<MetricCard
label="Inversión Restante Oreado"
:value="formatCurrency(metrics.inversionRestanteOreado.value)"
variant="warning"
/>
<MetricCard
label="Inversión Restante Mojado"
:value="formatCurrency(metrics.inversionRestanteMojado.value)"
variant="warning"
/>
<MetricCard
label="Inversión Restante Uva"
:value="formatCurrency(metrics.inversionRestanteUva.value)"
variant="warning"
/>
<MetricCard
label="Inversión Restante Esperada"
:value="formatCurrency(metrics.inversionRestanteEsperada.value)"
variant="danger"
class="font-bold"
/>
</div>
</UCard>
</template>
<script setup lang="ts">
import type { IngresosMetrics } from '~/composables/useIngresosMetrics'
defineProps<{
metrics: IngresosMetrics
}>()
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('es-GT', {
style: 'currency',
currency: 'GTQ'
}).format(value)
}
</script>

View File

@@ -0,0 +1,46 @@
<template>
<UCard class="brand-card border border-transparent">
<template #header>
<h2 class="text-xl font-bold brand-section-title">Inversión Hasta la Fecha</h2>
</template>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<MetricCard
label="Inversión en Uva"
:value="formatCurrency(metrics.inversionUva.value)"
variant="success"
/>
<MetricCard
label="Inversión en Oreado"
:value="formatCurrency(metrics.inversionOreado.value)"
variant="success"
/>
<MetricCard
label="Inversión en Mojado"
:value="formatCurrency(metrics.inversionMojado.value)"
variant="success"
/>
<MetricCard
label="Total Invertido"
:value="formatCurrency(metrics.totalInvertido.value)"
variant="primary"
class="font-bold"
/>
</div>
</UCard>
</template>
<script setup lang="ts">
import type { IngresosMetrics } from '~/composables/useIngresosMetrics'
defineProps<{
metrics: IngresosMetrics
}>()
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('es-GT', {
style: 'currency',
currency: 'GTQ'
}).format(value)
}
</script>

View File

@@ -0,0 +1,44 @@
<template>
<UCard class="brand-card border border-transparent">
<template #header>
<h2 class="text-xl font-bold brand-section-title">Secos Vendidos y Pérdidas</h2>
</template>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<MetricCard
label="Total QQ Secos por Vender"
:value="metrics.totalQqSecoPorVender.value.toFixed(2)"
unit="QQ"
variant="info"
/>
<MetricCard
label="Precio de Venta Promedio por QQ"
:value="formatCurrency(metrics.precioVentaPromedioPorQq.value)"
/>
<MetricCard
label="Precio de Compra Promedio por QQ"
:value="formatCurrency(metrics.precioCompraPromedioPorQq.value)"
/>
<MetricCard
label="Margen de Ganancia por QQ"
:value="formatCurrency(metrics.margenGananciaPorQq.value)"
:variant="metrics.margenGananciaPorQq.value > 0 ? 'success' : 'danger'"
/>
</div>
</UCard>
</template>
<script setup lang="ts">
import type { IngresosMetrics } from '~/composables/useIngresosMetrics'
defineProps<{
metrics: IngresosMetrics
}>()
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('es-GT', {
style: 'currency',
currency: 'GTQ'
}).format(value)
}
</script>

View File

@@ -0,0 +1,45 @@
<template>
<UCard class="brand-card border border-transparent">
<template #header>
<h2 class="text-xl font-bold brand-section-title">Totales de Ingreso y Compra</h2>
</template>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<MetricCard
label="Total QQ Seco Ingresado"
:value="metrics.totalQqSecoIngresado.value.toFixed(2)"
unit="QQ"
variant="primary"
/>
<MetricCard
label="Total QQ Seco Comprado"
:value="metrics.totalQqSecoComprado.value.toFixed(2)"
unit="QQ"
variant="success"
/>
<MetricCard
label="Precio Promedio Ponderado Uva"
:value="metrics.precioPromedioUvaPorQqLb.value.toFixed(2)"
unit="$/lb"
/>
<MetricCard
label="Precio Promedio Ponderado Oreado"
:value="metrics.precioPromedioOreadoPorQq.value.toFixed(2)"
unit="$/QQ"
/>
<MetricCard
label="Precio Promedio Ponderado Mojado"
:value="metrics.precioPromedioMojadoPorQq.value.toFixed(2)"
unit="$/QQ"
/>
</div>
</UCard>
</template>
<script setup lang="ts">
import type { IngresosMetrics } from '~/composables/useIngresosMetrics'
defineProps<{
metrics: IngresosMetrics
}>()
</script>

View File

@@ -0,0 +1,56 @@
<template>
<UCard class="brand-card border border-transparent">
<template #header>
<h2 class="text-xl font-bold brand-section-title">Totales Netos de Verde</h2>
</template>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<MetricCard
label="Total Lb Neto de Verde"
:value="metrics.totalLbNetoVerde.value.toFixed(2)"
unit="lb"
/>
<MetricCard
label="Precio Promedio Ponderado Pagado"
:value="metrics.precioPromedioVerdePagado.value.toFixed(2)"
unit="$/lb"
/>
<MetricCard
label="Total Lb Neto de Verde en Depósito"
:value="metrics.totalLbNetoVerdeDeposito.value.toFixed(2)"
unit="lb"
variant="info"
/>
<MetricCard
label="Inversión en Verde Hasta la Fecha"
:value="formatCurrency(metrics.inversionVerdeHastaFecha.value)"
variant="success"
/>
<MetricCard
label="Inversión Restante a Realizar en Verde"
:value="formatCurrency(metrics.inversionRestanteVerde.value)"
variant="warning"
/>
<MetricCard
label="Total Lb Neto Comprado de Verde"
:value="metrics.totalLbNetoCompradoVerde.value.toFixed(2)"
unit="lb"
/>
</div>
</UCard>
</template>
<script setup lang="ts">
import type { IngresosMetrics } from '~/composables/useIngresosMetrics'
defineProps<{
metrics: IngresosMetrics
}>()
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('es-GT', {
style: 'currency',
currency: 'GTQ'
}).format(value)
}
</script>

View File

@@ -0,0 +1,53 @@
<template>
<div class="bg-[#1c140c] rounded-lg p-4 border-l-4" :class="borderColor">
<h3 class="text-lg font-semibold mb-3 capitalize text-[var(--brand-text)]">{{ title }}</h3>
<div class="space-y-2">
<div class="flex justify-between items-center">
<span class="text-[var(--brand-text-muted)] text-sm">Total {{ unidad }}:</span>
<span class="font-medium text-[var(--brand-text)]">{{ metrics.value.totalCantidad.toFixed(2) }} {{ unidad }}</span>
</div>
<div class="flex justify-between items-center">
<span class="text-[var(--brand-text-muted)] text-sm">Precio promedio:</span>
<span class="font-medium text-[var(--brand-text)]">{{ formatCurrency(metrics.value.precioPromedio) }}</span>
</div>
<div class="flex justify-between items-center pt-2 border-t border-[#3a2a16]">
<span class="text-[var(--brand-text)] font-semibold">Total cobrado:</span>
<span class="font-bold text-green-400">{{ formatCurrency(metrics.value.totalCobrado) }}</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import type { RechazoMetrics } from '~/composables/useRechazosMetrics'
interface Props {
title: string
metrics: ComputedRef<RechazoMetrics>
unidad: 'libras' | 'galones'
color?: 'blue' | 'green' | 'yellow' | 'red' | 'purple' | 'pink'
}
const props = withDefaults(defineProps<Props>(), {
color: 'blue'
})
const borderColor = computed(() => {
const colors = {
blue: 'border-blue-500',
green: 'border-green-500',
yellow: 'border-yellow-500',
red: 'border-red-500',
purple: 'border-purple-500',
pink: 'border-pink-500'
}
return colors[props.color]
})
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('es-GT', {
style: 'currency',
currency: 'GTQ'
}).format(value)
}
</script>

View File

@@ -0,0 +1,69 @@
<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">Rechazos y Subproductos</h2>
<div class="rounded-lg border border-[#3a2a16] bg-[#1c140c] px-4 py-2">
<div class="text-xs text-[var(--brand-text-muted)] uppercase tracking-wide mb-1">Total Rechazos</div>
<div class="text-2xl font-bold text-green-400">{{ formatCurrency(totalRechazos.value) }}</div>
</div>
</div>
</template>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<RechazosRechazoCard
title="Chibolita"
:metrics="metrics.chibolita"
unidad="libras"
color="blue"
/>
<RechazosRechazoCard
title="Perico"
:metrics="metrics.perico"
unidad="libras"
color="green"
/>
<RechazosRechazoCard
title="Vano"
:metrics="metrics.vano"
unidad="galones"
color="yellow"
/>
<RechazosRechazoCard
title="Picadillo"
:metrics="metrics.picadillo"
unidad="galones"
color="red"
/>
<RechazosRechazoCard
title="Magalla"
:metrics="metrics.magalla"
unidad="galones"
color="purple"
/>
<RechazosRechazoCard
title="Pinta"
:metrics="metrics.pinta"
unidad="libras"
color="pink"
/>
</div>
</UCard>
</template>
<script setup lang="ts">
import type { RechazosMetrics } from '~/composables/useRechazosMetrics'
const props = defineProps<{
metrics: RechazosMetrics
}>()
const totalRechazos = computed(() => props.metrics.totalRechazos)
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('es-GT', {
style: 'currency',
currency: 'GTQ'
}).format(value)
}
</script>