/discovery/:id 에 외국인 환자용 주변 정보를 붙였다. 숙박·음식점·웰니스·관광·문화· 쇼핑·축제 125건과 이동 반경 기준 회복 동선. 다음 뷰성형외과 미팅용 프로토타입이다. 데이터 (scripts/fetch_medical_tourism.py → src/data/medicalTourism.json) 한국관광공사 TourAPI 영문(EngService2) 사전 수집. 실시간 호출이 아닌 이유는 영문 커버리지가 얇아 필터링이 많이 필요하고, 시연 중 외부 API 상태에 화면이 종속되지 않게 하기 위해서다. 좌표는 Naver 지역검색 실측(뷰성형외과의원, 봉은사로 107). 실측으로 드러난 것과 대응 - 영문 관광지(76)의 대부분이 관광지가 아니다. 반경 5km 100건 중 92건이 분류코드 A02020500 "Medical Tourism Sites"(categoryCode2 로 확인)이며 병원과 유치 에이전시다. 제목 키워드로는 "하이안과", "닥파인더코리아" 를 놓쳐 코드로 걸렀다. 거리순 상위 100건이 거의 다 여기라 페이징을 넣어야 실제 관광지가 나온다. - 스파·찜질방(A02020300/400)은 회복 여정에 맞아 wellness 로 분리했다. - 영문 축제는 areacode 필드가 비어 있어 areaCode 필터가 0건을 반환한다. 좌표 거리로 걸렀다. - TourAPI 이미지 URL 이 http 라 https 사이트에서 혼합 콘텐츠로 차단된다. 수집 단계에서 https 로 올린다. - 반경을 목적별로 나눴다. 회복기에 자주 가는 숙박·식사는 5km, 관광은 10km. 만들지 않은 것 - 평점·리뷰·영업시간: TourAPI 미제공이라 null 로 두고 화면에 "미연동" 으로 적었다. Google Places 키가 아직 비어 있다(신청 중). - 수술 전후 식이 적합성: 의학 판단이라 병원 입력만 쓴다. ClinicInputsPanel 에 diet_guide 항목을 더해 supporter_inputs 로 받고, 입력 전에는 "병원 확인 대기" 로 둔다. 개별 식당의 적합 여부를 추론하지 않는다. - 회복 단계가 며칠째인지: 병원 입력(recovery). 화면의 단계는 이동 반경으로만 정의해 의학적 함의를 담지 않는다. - 한계 4가지를 meta.limits 에 담아 섹션 하단 "측정 가능 범위" 에 그대로 띄운다. FilledIcons 에 Bed·Fork·Spa·MapPin·Ticket·Bag·Theater 7종 추가(라인 아이콘·이모지 금지 규칙에 따라 채움 SVG). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
89 lines
3.0 KiB
TypeScript
89 lines
3.0 KiB
TypeScript
/**
|
|
* 의료관광 연결 기능 타입.
|
|
*
|
|
* 데이터 출처는 한국관광공사 TourAPI 다국어(영문) 이며 `scripts/fetch_medical_tourism.py`
|
|
* 가 수집·필터링해 `src/data/medicalTourism.json` 으로 낸다.
|
|
*
|
|
* 원칙: 없는 값을 만들지 않는다.
|
|
* - rating/reviewCount/openingHours 는 TourAPI 가 주지 않는다. Google Places 승인 후 채운다.
|
|
* 그때까지 null 이며 화면은 빈 값을 그대로 "미연동"으로 보여준다.
|
|
* - 수술 전후 식이 적합성은 병원이 입력한 가이드로만 표시한다. 여기서 추론하지 않는다.
|
|
*/
|
|
|
|
/** 병원 반경 안에서 찾은 장소 한 곳. */
|
|
export interface TourPlace {
|
|
id: string;
|
|
title: string;
|
|
address: string;
|
|
image: string | null;
|
|
tel: string | null;
|
|
lat: number | null;
|
|
lng: number | null;
|
|
/** 병원으로부터의 거리(m). TourAPI 가 준 값을 그대로 쓰고, 없으면 좌표로 계산한다. */
|
|
distanceM: number | null;
|
|
/** 아래 셋은 TourAPI 미제공. Google Places 승인 전까지 null 이다. */
|
|
rating: number | null;
|
|
reviewCount: number | null;
|
|
openingHours: string | null;
|
|
}
|
|
|
|
/** 축제·행사. 영문 서비스는 areacode 가 비어 있어 좌표 거리로 걸렀다. */
|
|
export interface TourFestival extends TourPlace {
|
|
startDate: string | null;
|
|
endDate: string | null;
|
|
distanceKm: number;
|
|
}
|
|
|
|
export type PlaceCategory =
|
|
| 'stay'
|
|
| 'restaurant'
|
|
| 'wellness'
|
|
| 'attraction'
|
|
| 'culture'
|
|
| 'shopping';
|
|
|
|
export interface MedicalTourismData {
|
|
places: Record<PlaceCategory, TourPlace[]>;
|
|
festivals: TourFestival[];
|
|
meta: {
|
|
source: string;
|
|
fetchedAt: string;
|
|
origin: { lat: number; lng: number; label: string; coordSource: string };
|
|
radiusByType: Record<string, number>;
|
|
festivalRadiusKm: number;
|
|
counts: Record<string, Record<string, unknown>>;
|
|
/** 화면에 그대로 표시한다. 한계를 숨기지 않는다. */
|
|
limits: string[];
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 회복 단계. 며칠째인지는 의학 판단이므로 여기서 정하지 않는다.
|
|
* 이 단계는 "병원에서 얼마나 멀리 움직이는가"라는 이동 반경 기준이며,
|
|
* 각 단계가 수술 후 며칠에 해당하는지는 병원이 supporter_inputs 로 입력한다.
|
|
*/
|
|
export interface RecoveryStage {
|
|
id: string;
|
|
label: string;
|
|
/** 이 단계에서 권하는 이동 반경(m). 거리로만 정의하며 의학적 판단을 담지 않는다. */
|
|
maxDistanceM: number;
|
|
/** 이 단계에 배치할 장소 범주. */
|
|
categories: PlaceCategory[];
|
|
note: string;
|
|
}
|
|
|
|
/** 병원이 입력하는 값. 없으면 화면은 "병원 확인 대기"로 둔다. */
|
|
export interface ClinicRecoveryInput {
|
|
/** supporter_inputs.key = 'recovery' */
|
|
recoveryNote?: string;
|
|
/** supporter_inputs.key = 'diet_guide' */
|
|
dietGuide?: {
|
|
/** 회복 단계별 권장 음식 분류. 병원이 적은 그대로 쓴다. */
|
|
recommended?: string;
|
|
/** 회복 단계별 피해야 할 음식 분류. */
|
|
avoid?: string;
|
|
/** 단계가 며칠씩인지. */
|
|
stageDays?: string;
|
|
};
|
|
}
|