import { useState } from 'react'; /** * 해양환경관리법 제22조 기반 선박 발생 오염물 배출 규정 * 영해기선으로부터의 거리에 따라 배출 가능 여부 결정 * * 법률 근거: * https://lbox.kr/v2/statute/%ED%95%B4%EC%96%91%ED%99%98%EA%B2%BD%EA%B4%80%EB%A6%AC%EB%B2%95/%EB%B3%B8%EB%AC%B8%20%3E%20%EC%A0%9C3%EC%9E%A5%20%3E%20%EC%A0%9C1%EC%A0%88%20%3E%20%EC%A0%9C22%EC%A1%B0 * 선박에서의 오염방지에 관한 규칙 제8조[별표 2] 및 제14조 */ type Status = 'forbidden' | 'allowed' | 'conditional'; interface DischargeRule { category: string; item: string; zones: [Status, Status, Status, Status, Status]; // [~3NM, 3~12NM, 12~25NM, 25~50NM, 50NM+] condition?: string; } const RULES: DischargeRule[] = [ // 분뇨 { category: '분뇨', item: '분뇨마쇄소독장치', zones: ['forbidden', 'conditional', 'conditional', 'conditional', 'conditional'], condition: '항속 4노트 이상시 서서히 배출 / 400톤 미만 국내항해 선박은 3해리 이내 가능', }, { category: '분뇨', item: '분뇨저장탱크', zones: ['forbidden', 'forbidden', 'conditional', 'conditional', 'conditional'], condition: '항속 4노트 이상시 서서히 배출', }, { category: '분뇨', item: '분뇨처리장치', zones: ['allowed', 'allowed', 'allowed', 'allowed', 'allowed'], condition: '수산자원보호구역, 보호수면 및 육성수면은 불가', }, // 음식물찌꺼기 { category: '음식물찌꺼기', item: '미분쇄 음식물', zones: ['forbidden', 'forbidden', 'allowed', 'allowed', 'allowed'], }, { category: '음식물찌꺼기', item: '분쇄·연마 음식물 (25mm 이하)', zones: ['forbidden', 'conditional', 'allowed', 'allowed', 'allowed'], condition: '25mm 이하 개구 스크린 통과 가능시', }, // 화물잔류물 { category: '화물잔류물', item: '부유성 화물잔류물', zones: ['forbidden', 'forbidden', 'forbidden', 'allowed', 'allowed'], }, { category: '화물잔류물', item: '침강성 화물잔류물', zones: ['forbidden', 'forbidden', 'allowed', 'allowed', 'allowed'], }, { category: '화물잔류물', item: '화물창 세정수', zones: ['forbidden', 'forbidden', 'conditional', 'conditional', 'conditional'], condition: '해양환경에 해롭지 않은 일반세제 사용시', }, // 화물유 { category: '화물유', item: '화물유 섞인 평형수·세정수·선저폐수', zones: ['forbidden', 'forbidden', 'forbidden', 'forbidden', 'conditional'], condition: '항해 중, 순간배출률 1해리당 30L 이하, 기름오염방지설비 작동 중', }, // 유해액체물질 { category: '유해액체물질', item: '유해액체물질 섞인 세정수', zones: ['forbidden', 'forbidden', 'conditional', 'conditional', 'conditional'], condition: '자항선 7노트/비자항선 4노트 이상, 수심 25m 이상, 수면하 배출구 사용', }, // 폐기물 { category: '폐기물', item: '플라스틱 제품', zones: ['forbidden', 'forbidden', 'forbidden', 'forbidden', 'forbidden'], }, { category: '폐기물', item: '포장유해물질·용기', zones: ['forbidden', 'forbidden', 'forbidden', 'forbidden', 'forbidden'], }, { category: '폐기물', item: '중금속 포함 쓰레기', zones: ['forbidden', 'forbidden', 'forbidden', 'forbidden', 'forbidden'], }, ]; const ZONE_LABELS = ['~3해리', '3~12해리', '12~25해리', '25~50해리', '50해리+']; const ZONE_COLORS = ['#ef4444', '#f97316', '#eab308', '#22c55e', '#64748b']; function StatusBadge({ status }: { status: Status }) { if (status === 'forbidden') return ( 배출불가 ); if (status === 'allowed') return ( 배출가능 ); return ( 조건부 ); } interface DischargeZonePanelProps { lat: number; lon: number; distanceNm: number; zoneIndex: number; onClose: () => void; } export function DischargeZonePanel({ lat, lon, distanceNm, zoneIndex, onClose, }: DischargeZonePanelProps) { const zoneIdx = zoneIndex; const [expandedCat, setExpandedCat] = useState(null); const categories = [...new Set(RULES.map((r) => r.category))]; return (
{/* Header */}
🚢 오염물 배출 규정
해양환경관리법 제22조
{/* Location Info */}
선택 위치 {lat.toFixed(4)}°N, {lon.toFixed(4)}°E
영해기선 거리 {distanceNm.toFixed(1)} NM
{/* Zone indicator */}
{ZONE_LABELS.map((label, i) => (
{label}
))}
{/* Rules */}
{categories.map((cat) => { const catRules = RULES.filter((r) => r.category === cat); const isExpanded = expandedCat === cat; const allForbidden = catRules.every((r) => r.zones[zoneIdx] === 'forbidden'); const allAllowed = catRules.every((r) => r.zones[zoneIdx] === 'allowed'); const summaryColor = allForbidden ? '#ef4444' : allAllowed ? '#22c55e' : '#eab308'; return (
setExpandedCat(isExpanded ? null : cat)} style={{ padding: '8px 14px' }} >
{cat}
{allForbidden ? '전체 불가' : allAllowed ? '전체 가능' : '항목별 상이'} {isExpanded ? '▾' : '▸'}
{isExpanded && (
{catRules.map((rule, i) => (
{rule.item}
))} {catRules.some((r) => r.condition && r.zones[zoneIdx] !== 'forbidden') && (
{catRules .filter((r) => r.condition && r.zones[zoneIdx] !== 'forbidden') .map((r, i) => (
💡 {r.item}: {r.condition}
))}
)}
)}
); })}
{/* Footer */}
※ 거리는 영해기선 폴리곤 기준입니다. 구역은 버퍼 폴리곤 포함 여부로 판별됩니다.
); }