import { sampleProjects } from './sample-projects'; import { sampleLocations } from './sample-locations'; import { renderSamplePreview } from './sample-preview'; import { createSampleMap } from './sample-map'; import './sample-explorer.css'; export type Sample=typeof sampleProjects[number]; export const sampleExplorerMarkup=``; export function createSampleExplorer(root:HTMLElement,load:(sample:Sample)=>Promise):void{ const panel=root.querySelector('.sample-explorer')!,list=panel.querySelector('.sample-list')!,status=panel.querySelector('#landing-sample-status')!,button=panel.querySelector('.sample-load')!; let selected:Sample=sampleProjects[0],busy=false,previewToken=0; let map:ReturnType|undefined; const select=(sample:Sample,focus=true)=>{ if(busy)return;selected=sample;panel.dataset.selected=String(sample.sample);button.dataset.sample=String(sample.sample);status.textContent=sample.pierCount?'':'원본 프로젝트에 교각 형상이 없습니다. 실제 지반·지도 자료를 엽니다.'; button.disabled=false;button.textContent=sample.pierCount?'설계 프로젝트 불러오기 ↗':'설계 프로젝트 불러오기 ↗'; panel.querySelectorAll('[data-sample-row]').forEach(row=>{const active=Number(row.dataset.sampleRow)===sample.sample;row.classList.toggle('is-selected',active);row.setAttribute('aria-pressed',String(active));}); panel.querySelector('.sample-selection-info h3')!.textContent=sample.bridge; panel.querySelector('.sample-selection-info p')!.textContent=`${sampleLocations.find(p=>p.sample===sample.sample)?.types??'형식 미확인'} · 원본 교각 ${sample.pierCount}기`; panel.querySelector('.sample-selection-index')!.textContent=`PROJECT ${String(sample.sample).padStart(2,'0')}`; const loc=sampleLocations.find(p=>p.sample===sample.sample); panel.querySelector('.sample-location-name')!.textContent='프로젝트';const address=panel.querySelector('.sample-address')!;address.textContent=loc?.address??'주소 확인 불가';address.title='ArcGIS 역지오코딩 · 지도 좌표 기준 시·도 / 시·군 · 상세주소 제외'; panel.querySelector('.sample-crs')!.textContent=loc?`${loc.crs}${loc.crsAssumed?' · 원본 CRS 미확정':''}`:'좌표계 미확인'; panel.querySelector('.sample-survey')!.textContent=loc?`X(N) ${loc.surveyX.toFixed(3)} / Y(E) ${loc.surveyY.toFixed(3)} m`:'좌표 확인 불가'; panel.querySelector('.sample-wgs84')!.textContent=loc?`${loc.lat.toFixed(6)}° N / ${loc.lon.toFixed(6)}° E`:'변환 불가'; panel.querySelector('.sample-coordinate-basis')!.textContent=loc?`${loc.basis} · 프로그램 x=E/y=N`:'대표 좌표 없음'; const token=++previewToken;void renderSamplePreview(panel.querySelector('.sample-preview')!,sample,()=>token===previewToken); map?.highlight();if(focus)map?.focus(sample.sample); }; for(const sample of sampleProjects){const row=document.createElement('button');row.type='button';row.dataset.sampleRow=String(sample.sample);row.className='sample-row'; row.innerHTML=`${String(sample.sample).padStart(2,'0')}${sample.bridge}${sampleLocations.find(p=>p.sample===sample.sample)?.types??'미확인'} · 교각 ${sample.pierCount}기↗`; row.addEventListener('click',()=>select(sample));for(const event of ['pointerenter','focus'])row.addEventListener(event,()=>{row.classList.add('is-hovered');map?.hover(sample.sample);});for(const event of ['pointerleave','blur'])row.addEventListener(event,()=>{row.classList.remove('is-hovered');map?.hover(null);});list.append(row); } map=createSampleMap(panel,id=>{const sample=sampleProjects.find(s=>s.sample===id);if(sample){select(sample);list.querySelector(`[data-sample-row="${id}"]`)?.scrollIntoView({block:'nearest'});}},()=>selected.sample,()=>busy); button.addEventListener('click',async()=>{ if(busy)return;const target=selected;busy=true;button.disabled=true;button.textContent=`${target.bridge} 불러오는 중…`;list.querySelectorAll('button').forEach(b=>b.disabled=true);map!.refresh();status.textContent=`${target.bridge}: 실제 프로젝트 파일을 여는 중…`; try{await load(target);status.textContent=`${target.bridge}: 교각 ${target.pierCount}기 · 실제 지반/지도 복원 완료`;} catch(error){status.textContent=`${target.bridge}: ${(error as Error).message}`;panel.dataset.loadError=String(target.sample);} finally{busy=false;button.disabled=false;button.textContent=target.pierCount?'설계 프로젝트 불러오기 ↗':'설계 프로젝트 불러오기 ↗';list.querySelectorAll('button').forEach(b=>b.disabled=false);map!.refresh();} });select(selected,false); }