feat: 보고서 지도캡처 + 드론/CCTV/확산예측 UI 기능 개선 #91
@ -18,6 +18,11 @@ export function RightPanel({ onOpenBacktrack, onOpenRecalc, onOpenReport, detail
|
||||
const [shipExpanded, setShipExpanded] = useState(false)
|
||||
const [insuranceExpanded, setInsuranceExpanded] = useState(false)
|
||||
const [polygonResult, setPolygonResult] = useState<{ areaKm2: number; perimeterKm: number; particleCount: number; hullPoints: number } | null>(null)
|
||||
const [showCircleInput, setShowCircleInput] = useState(false)
|
||||
const [circleCenterLat, setCircleCenterLat] = useState('')
|
||||
const [circleCenterLon, setCircleCenterLon] = useState('')
|
||||
const [circleRadiusKm, setCircleRadiusKm] = useState('')
|
||||
const [circleResult, setCircleResult] = useState<{ areaKm2: number; circumferenceKm: number; centerLat: number; centerLon: number; radiusKm: number } | null>(null)
|
||||
|
||||
return (
|
||||
<div className="w-[300px] min-w-[300px] bg-bg-1 border-l border-border flex flex-col">
|
||||
@ -60,12 +65,115 @@ export function RightPanel({ onOpenBacktrack, onOpenRecalc, onOpenReport, detail
|
||||
📐 다각형 분석
|
||||
</button>
|
||||
<button
|
||||
onClick={() => alert('원 분석 기능은 향후 오픈 예정입니다.')}
|
||||
onClick={() => {
|
||||
setShowCircleInput(!showCircleInput)
|
||||
// 사고 지점 좌표를 기본값으로 설정
|
||||
if (!showCircleInput && detail?.spill) {
|
||||
if (!circleCenterLat) setCircleCenterLat(String(detail.spill.lat ?? ''))
|
||||
if (!circleCenterLon) setCircleCenterLon(String(detail.spill.lon ?? ''))
|
||||
}
|
||||
}}
|
||||
className="flex-1 py-2.5 px-2 rounded text-[10px] font-bold font-korean border cursor-pointer transition-colors hover:brightness-110"
|
||||
style={{ background: 'rgba(6,182,212,0.1)', border: '1px solid rgba(6,182,212,0.3)', color: 'var(--cyan)' }}>
|
||||
style={showCircleInput
|
||||
? { background: 'rgba(6,182,212,0.2)', border: '1px solid var(--cyan)', color: 'var(--cyan)' }
|
||||
: { background: 'rgba(6,182,212,0.1)', border: '1px solid rgba(6,182,212,0.3)', color: 'var(--cyan)' }
|
||||
}>
|
||||
⭕ 원 분석
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 원 분석 입력 폼 */}
|
||||
{showCircleInput && (
|
||||
<div className="flex flex-col gap-2 p-2.5 bg-bg-0 border border-[rgba(6,182,212,0.2)] rounded-md mb-2">
|
||||
<div className="text-[9px] font-bold text-primary-cyan font-korean">⭕ 원 분석 — 중심점 · 반경 입력</div>
|
||||
<div className="grid grid-cols-2 gap-1.5">
|
||||
<div>
|
||||
<label className="text-[8px] text-text-3 font-korean block mb-0.5">중심 위도 (°N)</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.0001"
|
||||
value={circleCenterLat}
|
||||
onChange={e => setCircleCenterLat(e.target.value)}
|
||||
placeholder="예: 34.7312"
|
||||
className="w-full px-2 py-1.5 bg-bg-3 border border-border rounded text-[10px] font-mono text-text-1 outline-none focus:border-[var(--cyan)] transition-colors"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[8px] text-text-3 font-korean block mb-0.5">중심 경도 (°E)</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.0001"
|
||||
value={circleCenterLon}
|
||||
onChange={e => setCircleCenterLon(e.target.value)}
|
||||
placeholder="예: 127.6845"
|
||||
className="w-full px-2 py-1.5 bg-bg-3 border border-border rounded text-[10px] font-mono text-text-1 outline-none focus:border-[var(--cyan)] transition-colors"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[8px] text-text-3 font-korean block mb-0.5">반경 (km)</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0.1"
|
||||
value={circleRadiusKm}
|
||||
onChange={e => setCircleRadiusKm(e.target.value)}
|
||||
placeholder="예: 3.0"
|
||||
className="w-full px-2 py-1.5 bg-bg-3 border border-border rounded text-[10px] font-mono text-text-1 outline-none focus:border-[var(--cyan)] transition-colors"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
const lat = parseFloat(circleCenterLat)
|
||||
const lon = parseFloat(circleCenterLon)
|
||||
const r = parseFloat(circleRadiusKm)
|
||||
if (isNaN(lat) || isNaN(lon) || isNaN(r) || r <= 0) {
|
||||
alert('중심 좌표와 반경을 올바르게 입력하세요.')
|
||||
return
|
||||
}
|
||||
const areaKm2 = Math.PI * r * r
|
||||
const circumferenceKm = 2 * Math.PI * r
|
||||
setCircleResult({ areaKm2, circumferenceKm, centerLat: lat, centerLon: lon, radiusKm: r })
|
||||
}}
|
||||
disabled={!circleCenterLat || !circleCenterLon || !circleRadiusKm}
|
||||
className="w-full py-2 rounded text-[10px] font-bold font-korean cursor-pointer transition-colors"
|
||||
style={{
|
||||
background: (circleCenterLat && circleCenterLon && circleRadiusKm) ? 'rgba(6,182,212,0.15)' : 'var(--bg3)',
|
||||
border: (circleCenterLat && circleCenterLon && circleRadiusKm) ? '1px solid var(--cyan)' : '1px solid var(--bd)',
|
||||
color: (circleCenterLat && circleCenterLon && circleRadiusKm) ? 'var(--cyan)' : 'var(--t3)',
|
||||
}}
|
||||
>
|
||||
⭕ 원 면적 계산
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 원 분석 결과 */}
|
||||
{circleResult && (
|
||||
<div className="flex flex-col gap-1.5 mb-2">
|
||||
<div className="text-[9px] font-bold text-primary-cyan font-korean mb-0.5">⭕ 원 분석 결과</div>
|
||||
<div className="grid grid-cols-2 gap-1">
|
||||
<div className="text-center py-2 px-1 bg-bg-0 border border-border rounded">
|
||||
<div className="text-sm font-extrabold font-mono text-primary-cyan">{circleResult.areaKm2.toFixed(2)}</div>
|
||||
<div className="text-[7px] text-text-3 font-korean">오염 면적 (km²)</div>
|
||||
</div>
|
||||
<div className="text-center py-2 px-1 bg-bg-0 border border-border rounded">
|
||||
<div className="text-sm font-extrabold font-mono text-status-orange">{circleResult.circumferenceKm.toFixed(1)}</div>
|
||||
<div className="text-[7px] text-text-3 font-korean">원 둘레 (km)</div>
|
||||
</div>
|
||||
<div className="text-center py-2 px-1 bg-bg-0 border border-border rounded">
|
||||
<div className="text-sm font-extrabold font-mono text-text-1">{circleResult.radiusKm.toFixed(1)}</div>
|
||||
<div className="text-[7px] text-text-3 font-korean">반경 (km)</div>
|
||||
</div>
|
||||
<div className="text-center py-2 px-1 bg-bg-0 border border-border rounded">
|
||||
<div className="text-[9px] font-bold font-mono text-text-2">{circleResult.centerLat.toFixed(4)}°N</div>
|
||||
<div className="text-[9px] font-bold font-mono text-text-2">{circleResult.centerLon.toFixed(4)}°E</div>
|
||||
<div className="text-[7px] text-text-3 font-korean">중심 좌표</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{polygonResult && (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<div className="text-[9px] font-bold text-purple-400 font-korean mb-0.5">📐 Convex Hull 다각형 분석 결과</div>
|
||||
|
||||
불러오는 중...
Reference in New Issue
Block a user