- Fix error de sintaxis SQL en cálculo de tickets 'at risk' - Fix error de timezone (offset-naive vs offset-aware datetimes) - Implementado sistema completo de SLA Management - Agregados endpoints: /sla/dashboard, /sla/violations, /sla/at-risk - Creadas vistas frontend para dashboard, violaciones y tickets en riesgo - Actualizado sistema de Celery para monitoreo automático de SLAs - Mejorada configuración de categorías con tiempos SLA personalizables - Corregidos problemas de proxy en configuración de Vite - Agregado troubleshooting guide en README Archivos principales modificados: - backend/app/api/v1/endpoints/sla.py (nuevo) - backend/app/api/schemas/sla.py (nuevo) - frontend-internal/src/routes/sla/ (nuevo módulo completo) - workers/app/tasks/sla_tasks.py (queries async mejoradas) Documentación: docs/changelog-2026-02-17.md
72 lines
1.7 KiB
Svelte
72 lines
1.7 KiB
Svelte
<script lang="ts">
|
|
export let value: number = 0; // Percentage 0-100
|
|
export let label: string = '';
|
|
export let size: 'sm' | 'md' | 'lg' = 'md';
|
|
|
|
$: color = getColor(value);
|
|
$: sizeClass = getSizeClass(size);
|
|
$: strokeDasharray = `${(value / 100) * 283} 283`;
|
|
|
|
function getColor(val: number): string {
|
|
if (val >= 95) return '#10B981'; // green
|
|
if (val >= 85) return '#FBBF24'; // yellow
|
|
if (val >= 70) return '#F97316'; // orange
|
|
return '#EF4444'; // red
|
|
}
|
|
|
|
function getSizeClass(s: string): { width: number; fontSize: string } {
|
|
switch (s) {
|
|
case 'sm':
|
|
return { width: 80, fontSize: 'text-lg' };
|
|
case 'lg':
|
|
return { width: 160, fontSize: 'text-4xl' };
|
|
default:
|
|
return { width: 120, fontSize: 'text-2xl' };
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="flex flex-col items-center">
|
|
<svg width={sizeClass.width} height={sizeClass.width} viewBox="0 0 100 100">
|
|
<!-- Background circle -->
|
|
<circle
|
|
cx="50"
|
|
cy="50"
|
|
r="45"
|
|
fill="none"
|
|
stroke="#E5E7EB"
|
|
stroke-width="10"
|
|
/>
|
|
|
|
<!-- Progress circle -->
|
|
<circle
|
|
cx="50"
|
|
cy="50"
|
|
r="45"
|
|
fill="none"
|
|
stroke={color}
|
|
stroke-width="10"
|
|
stroke-dasharray={strokeDasharray}
|
|
stroke-linecap="round"
|
|
transform="rotate(-90 50 50)"
|
|
style="transition: stroke-dasharray 0.5s ease;"
|
|
/>
|
|
|
|
<!-- Center text -->
|
|
<text
|
|
x="50"
|
|
y="50"
|
|
text-anchor="middle"
|
|
dominant-baseline="middle"
|
|
class="fill-current text-gray-900 font-bold"
|
|
font-size="20"
|
|
>
|
|
{value.toFixed(0)}%
|
|
</text>
|
|
</svg>
|
|
|
|
{#if label}
|
|
<p class="mt-2 text-sm font-medium text-gray-600">{label}</p>
|
|
{/if}
|
|
</div>
|