Files
web-app-launcher/src/lib/components/widget/integration/GaugeRenderer.svelte
T
alexei.dolgolyov 50e8519220 feat(service-integrations): phase 2 — integration widget & app form UI
- Add 6 renderer components: StatCard, Gauge, List, Progress, AlertBanner, Chart
- Add IntegrationWidget container with auto-refresh, loading, error states
- Add IntegrationAlertOverlay for layout-level critical alerts
- Add IntegrationConfigFields for dynamic form generation from Zod schemas
- Register integration type in WidgetRenderer
- Extend WidgetCreationForm with integration app/endpoint pickers
- Extend AppForm with integration config section and test connection button
- Add /api/integrations/alerts endpoint
2026-03-25 22:07:51 +03:00

48 lines
1.6 KiB
Svelte

<script lang="ts">
import type { GaugeData } from '$lib/server/integrations/types.js';
interface Props {
data: GaugeData;
}
let { data }: Props = $props();
const percentage = $derived(data.max > 0 ? Math.min((data.value / data.max) * 100, 100) : 0);
const color = $derived.by(() => {
const warn = data.thresholds?.warning ?? 60;
const crit = data.thresholds?.critical ?? 85;
if (percentage >= crit) return '#ef4444'; // red
if (percentage >= warn) return '#eab308'; // yellow
return '#22c55e'; // green
});
// SVG circle math
const radius = 40;
const circumference = 2 * Math.PI * radius;
const strokeDashoffset = $derived(circumference - (percentage / 100) * circumference);
</script>
<div class="flex flex-col items-center justify-center gap-2 p-3">
<div class="relative h-24 w-24">
<svg viewBox="0 0 100 100" class="h-full w-full -rotate-90">
<circle cx="50" cy="50" r={radius} fill="none" stroke="currentColor" stroke-width="8" class="text-muted/20" />
<circle
cx="50" cy="50" r={radius} fill="none"
stroke={color} stroke-width="8"
stroke-linecap="round"
stroke-dasharray={circumference}
stroke-dashoffset={strokeDashoffset}
class="transition-all duration-700 ease-out"
/>
</svg>
<div class="absolute inset-0 flex flex-col items-center justify-center">
<span class="text-lg font-bold text-foreground">{Math.round(percentage)}%</span>
</div>
</div>
<div class="text-center">
<span class="text-sm font-medium text-muted-foreground">{data.label}</span>
<span class="block text-xs text-muted-foreground/70">{data.value}{data.unit} / {data.max}{data.unit}</span>
</div>
</div>