PageSourceSearch

https://doksanlife-bepxkdw4.manus.space/assets/TongDistrictDashboard-CDzNWEtT.js

js doksanlife-bepxkdw4.manus.space collected 2026-10-03 05:01:19 UTC 17,689 bytes, 2 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Map-B-TEAGR_.js","assets/react-vendor-BnMHY5ab.js"])))=>i.map(i=>d[i]);
2import{t as P,_ as G}from"./index-DIAKUBAW.js";import{r as a,j as t}from"./react-vendor-BnMHY5ab.js";import{ak as H,M,j as J,H as Q,S as K,E as T,aa as U,aq as V}from"./icons-xNTpJIlh.js";const W=a.lazy(()=>G(()=>import("./Map-B-TEAGR_.js"),__vite__mapDeps([0,1])).then(s=>({default:s.MapView}))),F={lat:37.4689,lng:126.8973},_="doksan1-tong-snapshot-v1";function d(s){return new Intl.NumberFormat("ko-KR").format(s)}function $(s,x){if(s.getType()==="Point"){x.extend(s.get());return}s.getArray().forEach(l=>$(l,x))}function X(){const s=P.districtWork.tongSnapshot.useQuery(void 0,{staleTime:6e5}),[x,j]=a.useState(1),[l,R]=a.useState(""),[p,A]=a.useState("tong"),[f,O]=a.useState(!1),[v,z]=a.useState(""),[E,k]=a.useState(!1),[L,g]=a.useState("이전 방문 자료를 확인하고 있습니다."),b=a.useRef(null),w=a.useRef(null),h=a.useRef(null),m=s.data?.tongs??[],o=m.find(e=>e.tongNo===x)??m[0],I=Math.max(...m.map(e=>e.population),1),r=s.data?.boundaries.find(e=>e.tongNo===x),S=a.useMemo(()=>{const e=Number(l.replace(/[^0-9]/g,""));return[...l.trim()?m.filter(n=>n.tongNo===e||n.verifiedScope?.includes(l.trim())):m].sort((n,i)=>p==="population"?i.population-n.population:p==="households"?i.households-n.households:n.tongNo-i.tongNo)},[l,p,m]);a.useEffect(()=>{if(s.data)try{const e=JSON.parse(localStorage.getItem(_)??"null");if(!e)g(`${s.data.source.referenceMonth.replace("-",".")} 자료를 처음 확인했습니다.`);else if(e.referenceMonth===s.data.source.referenceMonth)g(`이전 방문과 같은 ${s.data.source.referenceMonth.replace("-",".")} 기준 자료입니다.`);else{const c=s.data.tongs.filter(n=>e.populations[String(n.tongNo)]!==n.population).length;g(`${e.referenceMonth.replace("-",".")} 이후 인구가 달라진 통 ${c}곳을 확인했습니다.`)}localStorage.setItem(_,JSON.stringify({referenceMonth:s.data.source.referenceMonth,populations:Object.fromEntries(s.data.tongs.map(c=>[String(c.tongNo),c.population]))}))}catch{g(`${s.data.source.referenceMonth.replace("-",".")} 기준 공식 자료입니다.`)}},[s.data]),a.useEffect(()=>{if(!("IntersectionObserver"in window)){k(!0);return}const e=new IntersectionObserver(([c])=>{c.isIntersecting&&(k(!0),e.disconnect())},{rootMargin:"600px"});return b.current&&e.observe(b.current),()=>e.disconnect()},[]);const y=a.useCallback(async()=>{const e=w.current;if(!e||!window.google?.maps||!o)return;if(h.current&&(h.current.map=null),h.current=null,e.data.forEach(u=>e.data.remove(u)),e.setCenter(F),e.setZoom(14),r){const u=e.data.addGeoJson(r.geoJson);e.data.setStyle({fillColor:"#E8753D",fillOpacity:.28,strokeColor:"#A7472A",strokeOpacity:1,strokeWeight:3});const N=new google.maps.LatLngBounds;u.forEach(B=>{const C=B.getGeometry();C&&$(C,N)}),N.isEmpty()||e.fitBounds(N,56);return}if(!o.mapQuery)return;const i=(await new google.maps.Geocoder().geocode({address:o.mapQuery,region:"KR"})).results[0]?.geometry.location;if(!i)return;const D=document.createElement("div");D.className="grid size-10 place-items-center rounded-full border-2 border-white bg-[#C85E32] text-sm font-black text-white shadow-lg",D.textContent=String(o.tongNo),h.current=new google.maps.marker.AdvancedMarkerElement({map:e,position:i,title:`${o.tongNo}통 공식 공고 관할 참고 위치`,content:D}),e.setCenter(i),e.setZoom(16)},[r,o]);return a.useEffect(()=>{f&&y()},[f,y]),t.jsx("section",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:149",ref:b,id:"tong-status",className:"scroll-mt-24 bg-[#173F38] py-16 text-white sm:py-24",children:t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:150",className:"container",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:151",className:"grid gap-8 lg:grid-cols-[0.78fr_1.22fr] lg:items-end",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:152",children:[t.jsxs("span",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:153",className:"inline-flex items-center gap-2 text-sm font-black tracking-[0.12em] text-[#F0C764]",children:[t.jsx(H,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:153",className:"size-4"})," 1~60통 생활현황"]}),t.jsx("h2",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:154",className:"font-display mt-3 text-4xl font-bold tracking-[-0.045em] sm:text-5xl",children:"우리 통의 인구와 구획을 한눈에"}),t.jsxs("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:155",className:"mt-5 max-w-2xl leading-7 text-white/70",children:["행정안전부 통·반 원자료를 통별로 합산했습니다. 아래 번호 보드는 ",t.jsx("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:155",className:"text-white",children:"통계 탐색용"}),"이며 지리적 경계 모양이 아닙니다. 지도에는 공식 자료가 있는 경우에만 실제 경계를 표시합니다."]})]}),t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:157",className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:[{label:"통",value:"60개",icon:M},{label:"총인구",value:s.data?d(s.data.source.population):"—",icon:J},{label:"세대",value:s.data?d(s.data.source.households):"—",icon:Q},{label:"공식 경계",value:`${s.data?.boundaries.length??0}/60`,icon:K}].map(e=>{const c=e.icon;return t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:160",className:"rounded-2xl bg-white/[0.08] p-4 ring-1 ring-white/10",children:[t.jsx(c,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:160",className:"size-4 text-[#F0C764]"}),t.jsx("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:160",className:"mt-3 block text-xl",children:e.value}),t.jsx("span",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:160",className:"mt-1 block text-[11px] text-white/55",children:e.label})]},e.label)})})]}),t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:165",className:"mt-10 rounded-[2rem] bg-[#F8F3E8] p-5 text-[#173F38] shadow-[0_24px_70px_rgba(0,0,0,0.2)] sm:p-8",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:166",className:"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:167",children:[t.jsx("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:168",className:"text-xs font-black tracking-[0.11em] text-[#C85E32]",children:"OFFICIAL MONTHLY SNAPSHOT"}),t.jsxs("h3",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:169",className:"mt-2 text-2xl font-black",children:[s.data?.source.referenceMonth.replace("-","년 "),"월말 기준"]}),t.jsxs("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:170",className:"mt-1 text-xs text-[#69746F]",children:[L," 주민등록 통계는 실시간이 아닌 월 1회 공표 자료입니다."]})]}),t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:172",className:"flex flex-wrap gap-2",children:[t.jsxs("a",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:173",href:s.data?.source.sourceUrl,target:"_blank",rel:"noreferrer",className:"inline-flex min-h-11 items-center gap-2 rounded-full bg-[#173F38] px-5 text-xs font-black text-white",children:["최신 공식 통계 확인 ",t.jsx(T,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:173",className:"size-3.5"})]}),t.jsxs("a",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:174",href:"https://www.geumcheon.go.kr/portal/contents.do?key=661",target:"_blank",rel:"noreferrer",className:"inline-flex min-h-11 items-center gap-2 rounded-full border border-[#D7D3C9] bg-white px-5 text-xs font-black",children:["내 통 문의 02-2627-2503 ",t.jsx(T,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:174",className:"size-3.5"})]})]})]}),t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:178",className:"mt-7 grid gap-7 xl:grid-cols-[1.05fr_0.95fr]",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:179",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:180",className:"grid gap-3 sm:grid-cols-[1fr_auto]",children:[t.jsxs("label",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:181",className:"relative block",children:[t.jsx("span",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:181",className:"sr-only",children:"통 번호 또는 관할 검색"}),t.jsx(U,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:181",className:"absolute left-4 top-1/2 size-4 -translate-y-1/2 text-[#78817D]"}),t.jsx("input",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:181",value:l,onCh
2ange:e=>R(e.target.value),className:"min-h-12 w-full rounded-xl border border-[#D9D5CA] bg-white pl-11 pr-4 text-sm outline-none focus:border-[#12645B]",placeholder:"예: 29통, 롯데캐슬"})]}),t.jsxs("select",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:182",value:p,onChange:e=>A(e.target.value),className:"min-h-12 rounded-xl border border-[#D9D5CA] bg-white px-4 text-sm font-bold","aria-label":"통 정렬 기준",children:[t.jsx("option",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:182",value:"tong",children:"통 번호순"}),t.jsx("option",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:182",value:"population",children:"인구 많은순"}),t.jsx("option",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:182",value:"households",children:"세대 많은순"})]})]}),t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:185",className:"mt-4 grid max-h-[420px] grid-cols-4 gap-2 overflow-y-auto pr-1 sm:grid-cols-6 md:grid-cols-8","aria-label":"통별 인구 현황 번호 보드",children:S.map(e=>{const c=e.population/I,n=e.tongNo===x;return t.jsxs("button",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:190",type:"button",onClick:()=>j(e.tongNo),"aria-pressed":n,className:`relative min-h-[72px] rounded-xl p-2 text-left ring-2 transition active:scale-[0.97] ${n?"ring-[#C85E32]":"ring-transparent hover:ring-[#12645B]/35"}`,style:{backgroundColor:`rgba(18, 100, 91, ${.09+c*.34})`},children:[t.jsxs("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:191",className:"block text-sm",children:[e.tongNo,"통"]}),t.jsxs("span",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:191",className:"mt-1 block text-[10px] font-bold text-[#4E625C]",children:[d(e.population),"명"]}),e.verifiedScope&&t.jsx("span",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:191",className:"absolute right-1.5 top-1.5 size-2 rounded-full bg-[#E8753D]","aria-label":"공식 공고 관할 참고 있음"})]},e.tongNo)})}),S.length===0&&t.jsx("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:196",className:"mt-5 rounded-xl bg-white p-5 text-center text-sm font-bold text-[#6F7874]",children:"검색한 통 또는 관할 참고 문구가 없습니다."}),t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:197",className:"mt-4 flex items-start gap-2 rounded-xl bg-[#EFE8D8] p-4 text-xs leading-5 text-[#6A6254]",children:[t.jsx(V,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:197",className:"mt-0.5 size-4 shrink-0 text-[#A76432]"}),t.jsxs("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:197",children:[t.jsx("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:197",children:"주황 점"}),"은 최근 통장 모집 공고에서 일부 관할 문구가 확인된 통입니다. 공고에 없는 통의 경계를 추정하지 않았습니다."]})]})]}),o&&t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:201",className:"overflow-hidden rounded-[1.6rem] bg-white shadow-sm ring-1 ring-black/[0.05]",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:202",className:"grid gap-3 bg-[#E5EFEB] p-5 sm:grid-cols-[1fr_auto] sm:items-start",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:203",children:[t.jsx("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:203",className:"text-xs font-black text-[#12645B]",children:"선택한 구획"}),t.jsxs("h3",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:203",className:"mt-1 text-3xl font-black",children:["독산1동 ",o.tongNo,"통"]})]}),t.jsx("span",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:204",className:`w-fit rounded-full px-3 py-1.5 text-[11px] font-black ${r?"bg-[#D9EFE2] text-[#29683C]":o.verifiedScope?"bg-[#FFF0D0] text-[#8A62
217]":"bg-[#EEECE7] text-[#6D716F]"}`,children:r?"공식 경계 표시":o.verifiedScope?"관할 참고 위치":"경계 자료 대기"})]}),t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:206",className:"grid grid-cols-2 gap-px bg-[#E8E5DD] sm:grid-cols-4",children:[{label:"인구",value:`${d(o.population)}명`},{label:"세대",value:`${d(o.households)}세대`},{label:"세대당",value:`${(o.population/o.households).toFixed(2)}명`},{label:"남/여",value:`${d(o.male)} / ${d(o.female)}`}].map(e=>t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:207",className:"bg-white p-4",children:[t.jsx("span",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:207",className:"text-[10px] font-bold text-[#7A837F]",children:e.label}),t.jsx("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:207",className:"mt-1 block text-sm",children:e.value})]},e.label))}),t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:209",className:"p-5",children:[t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:210",className:"min-h-[290px] overflow-hidden rounded-2xl bg-[#E8EFEA]",children:[v?t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:211",role:"alert",className:"grid min-h-[290px] place-items-center p-6 text-center text-sm",children:t.jsxs("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:211",children:[t.jsx(M,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:211",className:"mx-auto size-8 text-[#C85E32]"}),t.jsx("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:211",className:"mt-3 block",children:"지도를 불러오지 못했습니다"}),t.jsx("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:211",className:"mt-2 text-xs text-[#6C7671]",children:v})]})}):!f&&t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:211",className:"absolute"}),E&&t.jsx(a.Suspense,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:212",fallback:t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:212",className:"grid min-h-[290px] place-items-center text-sm font-bold",children:"지도를 불러오고 있습니다."}),children:t.jsx(W,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:212",className:"h-[290px]",ariaLabel:`독산1동 ${o.tongNo}통 공식 경계 또는 관할 참고 지도`,initialCenter:F,initialZoom:14,onMapReady:e=>{w.current=e,O(!0)},onMapError:z})}),!E&&t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:213",className:"grid min-h-[290px] place-items-center text-sm font-bold",children:"지도 영역에 가까워지면 불러옵니다."})]}),t.jsx("div",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:215",className:"mt-4",children:r?t.jsxs(t.Fragment,{children:[t.jsx("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",className:"text-sm",children:r.scopeLabel}),t.jsxs("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",className:"mt-1 text-xs text-[#6C7671]",children:[r.sourceLabel," · ",r.sourceDate]}),t.jsxs("a",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",href:r.sourceUrl,target:"_blank",rel:"noreferrer",className:"mt-3 inline-flex items-center gap-1 text-xs font-black text-[#12645B]",children:["경계 출처 원문 ",t.jsx(T,{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",className:"size-3"})]})]}):o.verifiedScope?t.jsxs(t.Fragment,{children:[t.jsxs("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",className:"text-sm",children:["공고 확인 관할: ",o.verifiedScope]}),t.jsxs("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",className:"mt-1 text-xs leading-5 text-[#6C7671]",children:[o.scopeSource,". 지도 표지는 공고 문구의 대표 위치이며 전체 경계가 아닙니다."]})]}):t.jsxs(t.Fragment,{children:[t.jsx("strong",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",className:"text-sm",children:"공개된 전체 관할 경계 자료를 기다리고 있습니다."}),t.jsx("p",{"data-loc":"client/src/components/life/TongDistrictDashboard.tsx:216",className:"mt-1 text-xs leading-5 text-[#6C7671]",children:"관리자가 금천구 공식 GeoJSON과 출처를 등록하기 전에는 임의 구획을 표시하지 않습니다."})]})})]})]})]})]})]})})}export{X as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.