gendesign/frontend/src/components/site-finder/ptica-v2/V2Gauge.tsx
Light1YT eb7290dcf0
All checks were successful
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 53s
CI / changes (pull_request) Successful in 5s
CI / openapi-codegen-check (pull_request) Successful in 1m51s
feat(site-finder): add Site Finder v2 cockpit route (ПТИЦА v2)
Port the approved ptica-v2 prototype to a new non-destructive route
/site-finder/analysis/{cad}/v2 — dark/light cockpit shell, real Leaflet
map (reuses PticaMapInner), 6 scan cards, lower/bottom grids, 11 drawers
and grounded chat. All values flow through the existing ptica-adapt layer
(real /analyze data or honest «—»). One beta link added on the analysis page.
2026-06-21 22:29:18 +05:00

72 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
/**
* V2Gauge — SVG progress ring (prototype `.gauge-wrap` / `.minigauge`). Renders a
* faint track + a colored arc whose length maps a 0..100 value. `null` value →
* muted "—" center (honest no-data, never a fake percentage). Tone selects the
* arc color via the scoped CSS tokens.
*
* Geometry mirrors the prototype: r=50 on a 120-box (big), r=30 on a 74-box
* (mini), r=26 on a 66-box (buy). dashoffset = circumference × (1 value/100).
*/
import styles from "@/app/site-finder/analysis/[cad]/v2/v2.module.css";
import type { PticaGauge } from "@/components/site-finder/ptica/ptica-adapt";
type Size = "big" | "mini" | "buy";
const GEOM: Record<Size, { box: number; r: number; stroke: number }> = {
big: { box: 120, r: 50, stroke: 9 },
mini: { box: 74, r: 30, stroke: 7 },
buy: { box: 66, r: 26, stroke: 7 },
};
// Tone → stroke color (map exception: Leaflet/SVG can't read CSS custom props in
// stroke attr reliably across themes, so we reference the var() here directly).
const TONE_STROKE: Record<PticaGauge["tone"], string> = {
good: "var(--accent-green)",
warn: "var(--accent-yellow)",
bad: "var(--accent-red)",
neutral: "var(--accent-cyan)",
};
interface Props {
gauge: PticaGauge;
size?: Size;
}
export function V2Gauge({ gauge, size = "big" }: Props) {
const { box, r, stroke } = GEOM[size];
const c = box / 2;
const circ = 2 * Math.PI * r;
const pct = gauge.value == null ? 0 : Math.max(0, Math.min(100, gauge.value));
const offset = circ * (1 - pct / 100);
const color = gauge.value == null ? "var(--text-soft)" : TONE_STROKE[gauge.tone];
return (
<svg viewBox={`0 0 ${box} ${box}`} aria-hidden="true">
<circle
cx={c}
cy={c}
r={r}
fill="none"
stroke="var(--border-faint)"
strokeWidth={stroke}
/>
{gauge.value != null && (
<circle
cx={c}
cy={c}
r={r}
fill="none"
stroke={color}
strokeWidth={stroke}
strokeLinecap="round"
strokeDasharray={circ}
strokeDashoffset={offset}
style={{ filter: "drop-shadow(0 0 5px var(--glow))" }}
/>
)}
</svg>
);
}