63 lines
2.0 KiB
TypeScript
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>
|
|
);
|
|
}
|
|
|