160 lines
5.7 KiB
TypeScript
160 lines
5.7 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
||
|
||
export const REGIONS: { label: string; cities: string[] }[] = [
|
||
{
|
||
label: '특별시 / 광역시',
|
||
cities: ['서울시', '부산시', '대구시', '인천시', '광주시', '대전시', '울산시', '세종시'],
|
||
},
|
||
{
|
||
label: '경기도',
|
||
cities: [
|
||
'수원시', '성남시', '고양시', '용인시', '부천시', '안산시', '안양시', '남양주시',
|
||
'화성시', '평택시', '의정부시', '시흥시', '파주시', '김포시', '광주시', '광명시',
|
||
'군포시', '하남시', '오산시', '이천시', '안성시', '구리시', '양주시', '포천시',
|
||
'여주시', '동두천시', '과천시', '가평군', '양평군', '연천군',
|
||
],
|
||
},
|
||
{
|
||
label: '강원도',
|
||
cities: [
|
||
'춘천시', '원주시', '강릉시', '동해시', '태백시', '속초시', '삼척시',
|
||
'홍천군', '횡성군', '영월군', '평창군', '정선군', '철원군', '화천군',
|
||
'양구군', '인제군', '고성군', '양양군',
|
||
],
|
||
},
|
||
{
|
||
label: '충청북도',
|
||
cities: [
|
||
'청주시', '충주시', '제천시',
|
||
'보은군', '옥천군', '영동군', '증평군', '진천군', '괴산군', '음성군', '단양군',
|
||
],
|
||
},
|
||
{
|
||
label: '충청남도',
|
||
cities: [
|
||
'천안시', '공주시', '보령시', '아산시', '서산시', '논산시', '계룡시', '당진시',
|
||
'금산군', '부여군', '서천군', '청양군', '홍성군', '예산군', '태안군',
|
||
],
|
||
},
|
||
{
|
||
label: '전라북도',
|
||
cities: [
|
||
'전주시', '군산시', '익산시', '정읍시', '남원시', '김제시',
|
||
'완주군', '진안군', '무주군', '장수군', '임실군', '순창군', '고창군', '부안군',
|
||
],
|
||
},
|
||
{
|
||
label: '전라남도',
|
||
cities: [
|
||
'목포시', '여수시', '순천시', '나주시', '광양시',
|
||
'담양군', '곡성군', '구례군', '고흥군', '보성군', '화순군', '장흥군', '강진군',
|
||
'해남군', '영암군', '무안군', '함평군', '영광군', '장성군', '완도군', '진도군', '신안군',
|
||
],
|
||
},
|
||
{
|
||
label: '경상북도',
|
||
cities: [
|
||
'포항시', '경주시', '김천시', '안동시', '구미시', '영주시', '영천시', '상주시', '문경시', '경산시',
|
||
'의성군', '청송군', '영양군', '영덕군', '청도군', '고령군', '성주군', '칠곡군',
|
||
'예천군', '봉화군', '울진군', '울릉군',
|
||
],
|
||
},
|
||
{
|
||
label: '경상남도',
|
||
cities: [
|
||
'창원시', '진주시', '통영시', '사천시', '김해시', '밀양시', '거제시', '양산시',
|
||
'의령군', '함안군', '창녕군', '고성군', '남해군', '하동군', '산청군', '함양군', '거창군', '합천군',
|
||
],
|
||
},
|
||
{
|
||
label: '제주도',
|
||
cities: ['제주시', '서귀포시'],
|
||
},
|
||
];
|
||
|
||
interface CitySelectModalProps {
|
||
selected: string;
|
||
onSelect: (city: string) => void;
|
||
onClose: () => void;
|
||
}
|
||
|
||
const CitySelectModal: React.FC<CitySelectModalProps> = ({ selected, onSelect, onClose }) => {
|
||
const [activeRegion, setActiveRegion] = useState<string | null>(
|
||
() => REGIONS.find(r => r.cities.includes(selected))?.label ?? null
|
||
);
|
||
|
||
useEffect(() => {
|
||
document.body.style.overflow = 'hidden';
|
||
return () => { document.body.style.overflow = ''; };
|
||
}, []);
|
||
|
||
const activeEntry = REGIONS.find(r => r.label === activeRegion);
|
||
const cities = activeEntry?.cities ?? [];
|
||
|
||
const handleSelect = (value: string) => {
|
||
onSelect(value === selected ? '' : value);
|
||
onClose();
|
||
};
|
||
|
||
return (
|
||
<div className="city-modal-backdrop" onClick={onClose}>
|
||
<div className="city-modal" onClick={e => e.stopPropagation()}>
|
||
<div className="city-modal-header">
|
||
<span className="city-modal-title">
|
||
{activeRegion ? (
|
||
<>
|
||
<button className="city-modal-back" onClick={() => setActiveRegion(null)}>←</button>
|
||
{activeRegion}
|
||
</>
|
||
) : '지역 선택'}
|
||
</span>
|
||
<button className="city-modal-close" onClick={onClose}>✕</button>
|
||
</div>
|
||
|
||
{activeRegion === null ? (
|
||
<div className="city-modal-grid">
|
||
{REGIONS.map(r => {
|
||
const isRegionSelected = selected === r.label;
|
||
const hasCitySelected = r.cities.includes(selected);
|
||
return (
|
||
<button
|
||
key={r.label}
|
||
className={`city-modal-region-item ${isRegionSelected || hasCitySelected ? 'has-selected' : ''}`}
|
||
onClick={() => setActiveRegion(r.label)}
|
||
>
|
||
<span>{r.label}</span>
|
||
{isRegionSelected && <span className="city-modal-region-badge">전체</span>}
|
||
{hasCitySelected && <span className="city-modal-region-badge">{selected}</span>}
|
||
<span className="city-modal-arrow">›</span>
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
) : (
|
||
<div className="city-modal-item-wrap">
|
||
{activeRegion !== '특별시 / 광역시' && (
|
||
<button
|
||
className={`city-modal-item city-modal-item-all ${selected === activeRegion ? 'active' : ''}`}
|
||
onClick={() => handleSelect(activeRegion!)}
|
||
>
|
||
전체
|
||
</button>
|
||
)}
|
||
{cities.map(city => (
|
||
<button
|
||
key={city}
|
||
className={`city-modal-item ${selected === city ? 'active' : ''}`}
|
||
onClick={() => handleSelect(city)}
|
||
>
|
||
{city}
|
||
</button>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default CitySelectModal;
|