gc-wing/apps/web/src/widgets/speed/SpeedProfilePanel.tsx
2026-02-15 11:22:38 +09:00

63 lines
2.0 KiB
TypeScript

import { ZONE_META } from "../../entities/zone/model/meta";
import { SPEED_MAX, VESSEL_TYPES } from "../../entities/vessel/model/meta";
import type { VesselTypeCode } from "../../entities/vessel/model/types";
type Props = {
selectedType: VesselTypeCode | null;
};
export function SpeedProfilePanel({ selectedType }: Props) {
const code = selectedType ?? "PT";
const t = VESSEL_TYPES[code];
const segs = t.speedProfile.map((s) => {
const left = (s.range[0] / SPEED_MAX) * 100;
const width = ((s.range[1] - s.range[0]) / SPEED_MAX) * 100;
const showText = width > 8;
const text = showText ? `${s.label}${s.primary ? ` ${s.typicalSpeed}kt` : ""}` : "";
return (
<div
key={`${s.label}-${s.range[0]}`}
className={`sseg ${s.primary ? "p" : ""}`}
style={{ left: `${left}%`, width: `${width}%`, background: s.color }}
>
{text}
</div>
);
});
const primary = t.speedProfile.filter((s) => s.primary);
return (
<div>
<div style={{ fontSize: 10, fontWeight: 700, color: t.color, marginBottom: 3 }}>
{t.icon} {code} {t.name}
</div>
<div className="sbar">{segs}</div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
{[0, 3, 5, 7, 10, 15].map((k) => (
<span key={k} style={{ fontSize: 7, color: "rgba(255,255,255,.2)" }}>
{k}
</span>
))}
</div>
<div style={{ marginTop: 2 }}>
{primary.map((s) => (
<span key={s.label} style={{ fontSize: 8, color: s.color, marginRight: 8 }}>
{s.label} {s.range[0]}~{s.range[1]}kt
</span>
))}
</div>
<div style={{ fontSize: 9, color: "var(--muted)", marginTop: 3 }}>
: <b style={{ color: "var(--text)" }}>{t.trajectory}</b> | :{" "}
{t.allowedZones.map((z) => (
<span key={z} style={{ color: ZONE_META[z].color, marginRight: 6 }}>
{ZONE_META[z].label}
</span>
))}
</div>
</div>
);
}