diff --git a/src/entities/slope/model/model.d.ts b/src/entities/slope/model/model.d.ts index 337ccfd..1ae6ded 100644 --- a/src/entities/slope/model/model.d.ts +++ b/src/entities/slope/model/model.d.ts @@ -1,38 +1,33 @@ -export type Level = - | '초급' - | '초중급' - | '중급' - | '중상급' - | '상급' - | '최상급' - | '파크'; +export type Level = '초급' | '초중급' | '중급' | '중상급' | '상급' | '최상급' | '파크'; -export type Slope = { - name: string, - difficulty: Level, - isDayOperating: true, - isNightOperating: true, - isLateNightOperating: true, - isDawnOperating: true, - isMidnightOperating: true -} +export type SlopeRaw = { + slopeId: number; + name: string; + difficulty: Level; + isDayOperating: boolean; + isNightOperating: boolean; + isLateNightOperating: boolean; + isDawnOperating: boolean; + isMidnightOperating: boolean; + webcamNo: number; +}; -export type Webcam = { - name: string, - number: 0, - description: string, - url: string -} +export type WebcamRaw = { + name: string; + number: number; + description: string; + url: string; +}; export type SlopeResponse = { - dayOperatingHours: string, - nightOperatingHours: string, - lateNightOperatingHours: string, - dawnOperatingHours: string, - midnightOperatingHours: string, - slopes: Slope[], - webcams: Webcam[] -} + dayOperatingHours: string; + nightOperatingHours: string; + lateNightOperatingHours: string; + dawnOperatingHours: string; + midnightOperatingHours: string; + slopes: SlopeRaw[]; + webcams: WebcamRaw[]; +}; export type ResortConstant = { MapComponent: ComponentType | StaticImageData; @@ -41,26 +36,25 @@ export type ResortConstant = { }; export type WebcamConstant = { - id: string; - name: string; + id: number; scale: number; position: { top: string; left: string; }; - src?: string; }; export type SlopeConstant = { - id: string; - level: Level; - name: string; - Element: React.FC; - webcamId?: string; - isOpen: boolean; + id: number; + PathAsset: ComponentType<{ + color?: string; + }>; }; export type Position = { x: number; y: number; }; + +export type Slope = SlopeRaw & SlopeConstant; +export type Webcam = WebcamRaw & WebcamConstant; diff --git a/src/entities/slope/model/resorts/eden.tsx b/src/entities/slope/model/resorts/eden.tsx index 8e03d71..486eefa 100644 --- a/src/entities/slope/model/resorts/eden.tsx +++ b/src/entities/slope/model/resorts/eden.tsx @@ -14,64 +14,37 @@ export const EDEN: ResortConstant = { MapComponent: MapImage, slopes: [ { - id: 'basic-slope', - level: '초급', - name: '베이직 슬로프', - Element: BasicSlopePath, - webcamId: 'basic-slope', - isOpen: true, + id: 145, + PathAsset: BasicSlopePath, }, { - id: 'main-slope', - level: '초급', - name: '메인 슬로프', - Element: MainSlopePath, - webcamId: 'basic-slope', - isOpen: true, + id: 146, + PathAsset: MainSlopePath, }, { - id: 'jupiter-slope', - level: '중급', - name: '쥬피터 슬로프', - Element: JupiterSlopePath, - webcamId: 'jupiter-slope', - isOpen: true, + id: 147, + PathAsset: JupiterSlopePath, }, { - id: 'saturn-slope', - level: '중급', - name: '새턴 슬로프', - Element: SaturnSlopePath, - isOpen: true, + id: 148, + PathAsset: SaturnSlopePath, }, { - id: 'uranus-slope', - level: '중급', - name: '우라누스', - Element: UranusSlopePath, - webcamId: 'uranus-slope', - isOpen: true, + id: 149, + PathAsset: UranusSlopePath, }, { - id: 'mercury-slope', - level: '상급', - name: '머큐리 슬로프', - Element: MercurySlopePath, - isOpen: true, + id: 150, + PathAsset: MercurySlopePath, }, { - id: 'venus-slope', - level: '상급', - name: '비너스 슬로프', - Element: VenusSlopePath, - webcamId: 'basic-slope', - isOpen: true, + id: 151, + PathAsset: VenusSlopePath, }, ], webcams: [ { - id: 'basic-slope', - name: '베이직 슬로프', + id: 1, position: { top: 'top-[52%]', left: 'left-[35%]', @@ -79,8 +52,7 @@ export const EDEN: ResortConstant = { scale: 1, }, { - id: 'jupiter-slope', - name: '쥬피터 슬로프', + id: 2, position: { top: 'top-[16%]', left: 'left-[50%]', @@ -88,8 +60,7 @@ export const EDEN: ResortConstant = { scale: 1, }, { - id: 'uranus-slope', - name: '우라누스 슬로프', + id: 3, position: { top: 'top-[32%]', left: 'left-[77%]', diff --git a/src/entities/slope/model/resorts/elysian-gangchon.tsx b/src/entities/slope/model/resorts/elysian-gangchon.tsx index 5e221db..db1c169 100644 --- a/src/entities/slope/model/resorts/elysian-gangchon.tsx +++ b/src/entities/slope/model/resorts/elysian-gangchon.tsx @@ -17,89 +17,49 @@ export const ELYSIAN_GANGCHON: ResortConstant = { MapComponent: ElysianGangchonMap, slopes: [ { - id: 'panda-slop', - level: '초급', - name: '팬더슬로프', - Element: PandaSlopPath, - webcamId: 'sub-house', - isOpen: true, + id: 112, + PathAsset: PandaSlopPath, }, { - id: 'rabbit-slop', - level: '초급', - name: '래빗슬로프', - Element: RabbitSlopPath, - webcamId: 'sub-house', - isOpen: true, + id: 113, + PathAsset: RabbitSlopPath, }, { - id: 'dragon-slop', - level: '중급', - name: '드래곤슬로프', - Element: DragonSlopPath, - webcamId: 'alp-house', - isOpen: true, + id: 114, + PathAsset: DragonSlopPath, }, { - id: 'horse-slop', - level: '중급', - name: '호스슬로프', - Element: HorseSlopPath, - webcamId: 'alp-house', - isOpen: true, + id: 115, + PathAsset: HorseSlopPath, }, { - id: 'pegasus-slop', - level: '중급', - name: '페가수스슬로프', - Element: PegasusSlopPath, - webcamId: 'ski-house', - isOpen: true, + id: 116, + PathAsset: PegasusSlopPath, }, { - id: 'zebra-slop', - level: '중급', - name: '제브라슬로프', - Element: ZebraSlopPath, - webcamId: 'ski-house', - isOpen: true, + id: 117, + PathAsset: ZebraSlopPath, }, { - id: 'deer-slop', - level: '중급', - name: '디어슬로프', - Element: DeerSlopPath, - isOpen: true, + id: 118, + PathAsset: DeerSlopPath, }, { - id: 'puma-slop', - level: '중급', - name: '퓨마슬로프', - Element: PumaSlopPath, - webcamId: 'alp-house', - isOpen: true, + id: 119, + PathAsset: PumaSlopPath, }, { - id: 'leopard-slop', - level: '상급', - name: '래퍼드슬로프', - Element: LeopardSlopPath, - webcamId: 'ski-house', - isOpen: true, + id: 120, + PathAsset: LeopardSlopPath, }, { - id: 'jaguar-slop', - level: '상급', - name: '제규어슬로프', - Element: JaguarSlopPath, - webcamId: 'ski-house', - isOpen: true, + id: 121, + PathAsset: JaguarSlopPath, }, ], webcams: [ { - id: 'sub-house', - name: '서브하우스', + id: 1, position: { top: 'top-[86%]', left: 'left-[19%]', @@ -107,8 +67,7 @@ export const ELYSIAN_GANGCHON: ResortConstant = { scale: 1, }, { - id: 'alp-house', - name: '알프하우스', + id: 2, position: { top: 'top-[7%]', left: 'left-[27%]', @@ -116,8 +75,7 @@ export const ELYSIAN_GANGCHON: ResortConstant = { scale: 1, }, { - id: 'ski-house', - name: '스키하우스', + id: 3, position: { top: 'top-[83%]', left: 'left-[80%]', diff --git a/src/entities/slope/model/resorts/gonjiam.tsx b/src/entities/slope/model/resorts/gonjiam.tsx index 1411be0..69a6290 100644 --- a/src/entities/slope/model/resorts/gonjiam.tsx +++ b/src/entities/slope/model/resorts/gonjiam.tsx @@ -17,132 +17,86 @@ export const GONJIAM: ResortConstant = { MapComponent: GonjiamMap, slopes: [ { - id: 'whynot-slop', - level: '초중급', - name: '와이낫슬로프', - Element: WhynotSlopPath, - webcamId: 'upper-base', - isOpen: true, + id: 1, + PathAsset: WhynotSlopPath, }, { - id: 'gram1-slop', - level: '상급', - name: '그램슬로프1', - Element: Gram1SlopPath, - isOpen: true, + id: 2, + PathAsset: Gram1SlopPath, }, { - id: 'gram2-slop', - level: '중급', - name: '그램슬로프 2', - Element: Gram2SlopPath, - isOpen: true, + id: 3, + PathAsset: Gram2SlopPath, }, { - id: 'cnp1-slop', - level: '초중급', - name: 'CNP슬로프 1', - Element: CNP1SlopPath, - webcamId: 'cnp-top', - isOpen: true, + id: 4, + PathAsset: CNP1SlopPath, }, { - id: 'cnp2-slop', - level: '상급', - name: 'CNP슬로프 2', - Element: CNP2SlopPath, - isOpen: true, + id: 5, + PathAsset: CNP2SlopPath, }, { - id: 'thinkyou1-slop', - level: '중상급', - name: '씽큐리프트 1', - Element: Thinkyou1SlopPath, - webcamId: 'cnp-top', - isOpen: true, + id: 6, + PathAsset: Thinkyou1SlopPath, }, { - id: 'thinkyou2-slop', - level: '초중급', - name: '씽큐리프트 2', - Element: Thinkyou2SlopPath, - webcamId: 'upper-base', - isOpen: true, + id: 7, + PathAsset: Thinkyou2SlopPath, }, { - id: 'thinkyou3-slop', - level: '중상급', - name: '씽큐리프트 3', - Element: Thinkyou3SlopPath, - isOpen: true, + id: 8, + PathAsset: Thinkyou3SlopPath, }, { - id: 'thinkyou-bridge-slop', - level: '상급', - name: '씽큐브릿지', - Element: ThinkyouBridgeSlopPath, - isOpen: true, + id: 9, + PathAsset: ThinkyouBridgeSlopPath, }, { - id: 'whisen-slop', - level: '초급', - name: '휘센슬로프', - Element: WhisenSlopPath, - webcamId: 'whisen-base', - isOpen: true, + id: 10, + PathAsset: WhisenSlopPath, }, ], webcams: [ { - id: 'whisen-base', - name: '초중급 베이스', + id: 1, position: { top: 'top-[82%]', left: 'left-[51%]', }, - src: '/api/webcam?url=http://konjiam.live.cdn.cloudn.co.kr/konjiam/cam03.stream/playlist.m3u8', scale: 1, }, { - id: 'upper-base', - name: '중상급 베이스', + id: 2, position: { top: 'top-[85%]', left: 'left-[43%]', }, - //TODO: 해당 URL만 작동 안함 - // src: '/api/webcam?url=http://konjiam.live.cdn.cloudn.co.kr/konjiam/cam04.stream/playlist.m3u8', scale: 1, }, { - id: 'cnp-top', - name: '정상부 슬로프', + id: 3, position: { top: 'top-[34%]', left: 'left-[21%]', }, scale: 1, - src: '/api/webcam?url=http://konjiam.live.cdn.cloudn.co.kr/konjiam/cam02.stream/playlist.m3u8', }, { - id: 'top-rest-area', - name: '정상 휴게소', + id: 4, position: { top: 'top-[7%]', left: 'left-[20%]', }, scale: 1, - src: '/api/webcam?url=http://konjiam.live.cdn.cloudn.co.kr/konjiam/cam01.stream/playlist.m3u8', }, { - id: 'middle-slope', - name: '중간 슬로프', + id: 5, position: { top: 'top-[60%]', left: 'left-[43%]', }, scale: 1, - src: '/api/webcam?url=http://konjiam.live.cdn.cloudn.co.kr/konjiam/cam05.stream/playlist.m3u8', }, ], }; diff --git a/src/entities/slope/model/resorts/high1.tsx b/src/entities/slope/model/resorts/high1.tsx index 93aa680..1149077 100644 --- a/src/entities/slope/model/resorts/high1.tsx +++ b/src/entities/slope/model/resorts/high1.tsx @@ -23,303 +23,213 @@ export const HIGH1: ResortConstant = { MapComponent: High1Map, slopes: [ { - id: 'zeus1-slop', - level: '초급', - name: '제우스슬로프 1', - Element: Zeus1SlopPath, - isOpen: true, + id: 1, + PathAsset: Zeus1SlopPath, }, { - id: 'zeus2-slop', - level: '초급', - name: '제우스슬로프 2', - Element: Zeus2SlopPath, - webcamId: 'zeus2-entry', - isOpen: true, + id: 2, + PathAsset: Zeus2SlopPath, }, { - id: 'zeus3-slop', - level: '초급', - name: '제우스슬로프 3', - Element: Zeus3SlopPath, - webcamId: 'zeus3-entry', - isOpen: true, + id: 3, + PathAsset: Zeus3SlopPath, }, { - id: 'zeus3-1-slop', - level: '초급', - name: '제우스슬로프 3-1', - Element: Zeus3Sub1SlopPath, - isOpen: true, + id: 4, + PathAsset: Zeus3Sub1SlopPath, }, { - id: 'victoria1-slop', - level: '상급', - name: '빅토리아슬로프 1', - Element: Victoria1SlopPath, - webcamId: 'victoria1-entry', - isOpen: true, + id: 5, + PathAsset: Victoria1SlopPath, }, { - id: 'victoria2-slop', - level: '상급', - name: '빅토리아슬로프 2', - Element: Victoria2SlopPath, - isOpen: true, + id: 6, + PathAsset: Victoria2SlopPath, }, { - id: 'hera1-slop', - level: '중급', - name: '헤라슬로프 1', - Element: Hera1SlopPath, - isOpen: true, + id: 8, + PathAsset: Hera1SlopPath, }, { - id: 'hera2-slop', - level: '중상급', - name: '헤라슬로프 2', - Element: Hera2SlopPath, - webcamId: 'hera2-entry', - isOpen: true, + id: 9, + PathAsset: Hera2SlopPath, }, { - id: 'hera3-slop', - level: '상급', - name: '헤라슬로프 3', - Element: Hera3SlopPath, - isOpen: true, + id: 10, + PathAsset: Hera3SlopPath, }, { - id: 'apollo1-slop', - level: '상급', - name: '아폴로슬로프 1', - Element: Apollo1SlopPath, - isOpen: true, + id: 11, + PathAsset: Apollo1SlopPath, }, { - id: 'apollo2-slop', - level: '상급', - name: '아폴로슬로프 2', - Element: Apollo2SlopPath, - isOpen: true, + id: 12, + PathAsset: Apollo2SlopPath, }, { - id: 'apollo3-slop', - level: '상급', - name: '아폴로슬로프 3', - Element: Apollo3SlopPath, - isOpen: true, + id: 13, + PathAsset: Apollo3SlopPath, }, { - id: 'apollo4-slop', - level: '상급', - name: '아폴로슬로프 4', - Element: Apollo4SlopPath, - webcamId: 'apollo4-mid', - isOpen: true, + id: 14, + PathAsset: Apollo4SlopPath, }, { - id: 'apollo6-slop', - level: '상급', - name: '아폴로슬로프 6', - Element: Apollo6SlopPath, - isOpen: true, + id: 16, + PathAsset: Apollo6SlopPath, }, { - id: 'athena2-slop', - level: '중급', - name: '아테나슬로프 2', - Element: Athena2SlopPath, - webcamId: 'athena2-entry', - isOpen: true, + id: 18, + PathAsset: Athena2SlopPath, }, { - id: 'athena3-slop', - level: '초급', - name: '아테나슬로프 3', - Element: Athena3SlopPath, - isOpen: true, + id: 19, + PathAsset: Athena3SlopPath, }, ], webcams: [ { - id: 'zeus2-entry', - name: '제우스2번 슬로프 입구', + id: 1, position: { top: 'top-[6%]', left: 'left-[45%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch1.stream/playlist.m3u8', scale: 2, }, { - id: 'hera2-entry', - name: '헤라2번 슬로프 입구', + id: 2, position: { top: 'top-[10%]', left: 'left-[50%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch2.stream/playlist.m3u8', scale: 2, }, { - id: 'highone-top', - name: '하이원 탑', + id: 3, position: { top: 'top-[6%]', left: 'left-[54%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch3.stream/playlist.m3u8', scale: 2, }, { - id: 'athena1-entry', - name: '아테나1번 슬로프', + id: 4, position: { top: 'top-[30%]', left: 'left-[65%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch4.stream/playlist.m3u8', scale: 2, }, { - id: 'mountain-hub-base', - name: '마운틴 허브 베이스', + id: 5, position: { top: 'top-[35%]', left: 'left-[61%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch5.stream/playlist.m3u8', scale: 2, }, { - id: 'athena2-entry', - name: '아테나2번 슬로프', + id: 6, position: { top: 'top-[40%]', left: 'left-[66%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch6.stream/playlist.m3u8', scale: 2, }, { - id: 'mountain-base', - name: '마운틴 베이스', + id: 7, position: { top: 'top-[68%]', left: 'left-[78%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch7.stream/playlist.m3u8', scale: 2, }, { - id: 'athena2-bottom', - name: '아테나2번 슬로프 하단', + id: 8, position: { top: 'top-[76%]', left: 'left-[73%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch8.stream/playlist.m3u8', scale: 2, }, { - id: 'victoria-top', - name: '빅토리아 상단', + id: 9, position: { top: 'top-[17%]', left: 'left-[17%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch9.stream/playlist.m3u8', scale: 2, }, { - id: 'zeus2-slope', - name: '제우스 2번', + id: 10, position: { top: 'top-[34%]', left: 'left-[38%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch10.stream/playlist.m3u8', scale: 2, }, { - id: 'valley-hub-base', - name: '밸리 허브 베이스', + id: 11, position: { top: 'top-[40%]', left: 'left-[40%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch11.stream/playlist.m3u8', scale: 2, }, { - id: 'victoria1-entry', - name: '빅토리아1번 슬로프', + id: 12, position: { top: 'top-[48%]', left: 'left-[43%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch12.stream/playlist.m3u8', scale: 2, }, { - id: 'zeus3-entry', - name: '제우스3번 슬로프', + id: 13, position: { top: 'top-[50%]', left: 'left-[36%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch13.stream/playlist.m3u8', scale: 2, }, { - id: 'zeus3-mid', - name: '제우스3번 중단부', + id: 14, position: { top: 'top-[58%]', left: 'left-[40%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch14.stream/playlist.m3u8', scale: 2, }, { - id: 'apollo4-mid', - name: '아폴로4번 중단부', + id: 15, position: { top: 'top-[58%]', left: 'left-[52%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch15.stream/playlist.m3u8', scale: 2, }, { - id: 'apollo-base', - name: '아폴로 베이스', + id: 16, position: { top: 'top-[71%]', left: 'left-[44%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch16.stream/playlist.m3u8', scale: 2, }, { - id: 'zeus3-bottom', - name: '제우스3번 하단', + id: 17, position: { top: 'top-[86%]', left: 'left-[46%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch17.stream/playlist.m3u8', scale: 2, }, { - id: 'valley-base', - name: '밸리 베이스', + id: 18, position: { top: 'top-[86%]', left: 'left-[39%]', }, - src: '/api/webcam?url=http://59.30.12.195:1935/live/_definst_/ch18.stream/playlist.m3u8', scale: 2, }, ], diff --git a/src/entities/slope/model/resorts/jisan.tsx b/src/entities/slope/model/resorts/jisan.tsx index cafb1b4..d7e0ddf 100644 --- a/src/entities/slope/model/resorts/jisan.tsx +++ b/src/entities/slope/model/resorts/jisan.tsx @@ -15,72 +15,41 @@ export const JISAN: ResortConstant = { MapComponent: MapImage, slopes: [ { - id: 'lemon1-lift', - level: '초급', - name: '레몬 리프트 1', - Element: Lemon1LiftPath, - webcamId: 'lemon-station', - isOpen: true, + id: 32, + PathAsset: Lemon1LiftPath, }, { - id: 'lemon1-1-lift', - level: '초급', - name: '레몬 리프트 1-1', - Element: Lemon1Sub1LiftPath, - isOpen: false, + id: 33, + PathAsset: Lemon1Sub1LiftPath, }, { - id: 'orange2-lift', - level: '중급', - name: '오렌지 리프트 2', - Element: Orange2LiftPath, - webcamId: 'orange-station', - isOpen: true, + id: 34, + PathAsset: Orange2LiftPath, }, { - id: 'orange3-lift', - level: '중급', - name: '오렌지 리프트 3', - Element: Orange3LiftPath, - webcamId: 'new-orange-station', - isOpen: true, + id: 35, + PathAsset: Orange3LiftPath, }, { - id: 'new-orange-lift', - level: '상급', - name: '뉴오렌지 리프트', - Element: NewOrangeLiftPath, - isOpen: true, + id: 36, + PathAsset: NewOrangeLiftPath, }, { - id: 'blue-lift', - level: '상급', - name: '블루 리프트 5', - Element: BlueLiftPath, - webcamId: 'blue-station', - isOpen: true, + id: 37, + PathAsset: BlueLiftPath, }, { - id: 'silver6-lift', - level: '최상급', - name: '실버 리프트 6', - Element: Silver6LiftPath, - webcamId: '5-station', - isOpen: true, + id: 38, + PathAsset: Silver6LiftPath, }, { - id: 'silver7-lift', - level: '중상급', - name: '실버 리프트 7', - Element: Silver7LiftPath, - webcamId: 'silver-station', - isOpen: true, + id: 39, + PathAsset: Silver7LiftPath, }, ], webcams: [ { - id: 'lemon-station', - name: '레몬 탑승장', + id: 1, position: { top: 'top-[84%]', left: 'left-[20%]', @@ -88,8 +57,7 @@ export const JISAN: ResortConstant = { scale: 1, }, { - id: 'orange-station', - name: '오렌지 탑승장', + id: 2, position: { top: 'top-[74%]', left: 'left-[31%]', @@ -97,50 +65,44 @@ export const JISAN: ResortConstant = { scale: 1, }, { - id: 'blue-station', - name: '블루 탑승장', - scale: 1, + id: 3, position: { - top: 'top-[69%]', - left: 'left-[56%]', + top: 'top-[64%]', + left: 'left-[38%]', }, + scale: 1, }, { - id: 'silver-station', - name: '실버 탑승장', - scale: 1, + id: 4, position: { - top: 'top-[72%]', - left: 'left-[68%]', + top: 'top-[69%]', + left: 'left-[56%]', }, + scale: 1, }, { - id: '5-station', - name: '5번 슬로프', - scale: 1, - + id: 5, position: { top: 'top-[47%]', left: 'left-[37%]', }, + scale: 1, }, { - id: 'new-orange-station', - name: '뉴오렌지 탑승장', - scale: 1, + id: 6, position: { - top: 'top-[64%]', - left: 'left-[38%]', + top: 'top-[72%]', + left: 'left-[68%]', }, + scale: 1, }, { - id: 'jisan-overview', - name: '지산 전경', - scale: 1, + id: 7, position: { top: 'top-[38%]', left: 'left-[52%]', }, + scale: 1, }, ], }; diff --git a/src/entities/slope/model/resorts/muju.tsx b/src/entities/slope/model/resorts/muju.tsx index 1b96377..b8bbb61 100644 --- a/src/entities/slope/model/resorts/muju.tsx +++ b/src/entities/slope/model/resorts/muju.tsx @@ -5,24 +5,24 @@ import AllegroPath from '../image/muju/allegro-path'; import CadenzaSlopePath from '../image/muju/cadenza-slope-path'; import ConnectionSlopePath from '../image/muju/connection-slope-path'; import EasternSlopePath from '../image/muju/eastern-slope-path'; -import FlamingoPath from '../image/muju/flamingo-path'; +// import FlamingoPath from '../image/muju/flamingo-path'; import FreewayPath from '../image/muju/freeway-path'; -import Freeway2Path from '../image/muju/freeway2-path'; +// import Freeway2Path from '../image/muju/freeway2-path'; import MinuetPath from '../image/muju/minuet-path'; -import ModeratoPath from '../image/muju/moderato-path'; +// import ModeratoPath from '../image/muju/moderato-path'; import MozartPath from '../image/muju/mozart-path'; import PanoramaPath from '../image/muju/panorama-path'; import PolkaSlopePath from '../image/muju/polka-slope-path'; -import RGardnerSlopePath from '../image/muju/r-gardner-slope-path'; +// import RGardnerSlopePath from '../image/muju/r-gardner-slope-path'; import RaidersHighestPath from '../image/muju/raiders-highest-path'; import RaidersLowestPath from '../image/muju/raiders-lowest-path'; import RookiehillSlopePath from '../image/muju/rookiehill-slope-path'; -import RusutsuSlopePath from '../image/muju/rusutsu-slope-path'; -import ShortcutSlopePath from '../image/muju/shortcut-slope-path'; +// import RusutsuSlopePath from '../image/muju/rusutsu-slope-path'; +// import ShortcutSlopePath from '../image/muju/shortcut-slope-path'; import SilkroadPath from '../image/muju/silkroad-path'; import SoyokgihangPath from '../image/muju/soyokgihang-path'; import SpitchLowestPath from '../image/muju/spitch-lowest-path'; -import SpitchSlopePath from '../image/muju/spitch-slope-path'; +// import SpitchSlopePath from '../image/muju/spitch-slope-path'; import SundownSlopePath from '../image/muju/sundown-slope-path'; import TurboSlopePath from '../image/muju/turbo-slope-path'; import WaltzSlopePath from '../image/muju/waltz-slope-path'; @@ -34,288 +34,177 @@ export const MUJU: ResortConstant = { MapComponent: MujuMap, slopes: [ { - id: 'eastern-slope', - level: '초급', - name: '이스턴슬로프', - Element: EasternSlopePath, - webcamId: 'mansun-house', - isOpen: true, + id: 74, + PathAsset: EasternSlopePath, }, { - id: 'soyokgihang', - level: '초급', - name: '서역기행', - Element: SoyokgihangPath, - webcamId: 'heidi-house', - isOpen: true, + id: 75, + PathAsset: SoyokgihangPath, }, { - id: 'spitch-lowest', - level: '초급', - name: '스피츠 하단', - Element: SpitchLowestPath, - webcamId: 'seolcheon-house', - isOpen: true, + id: 76, + PathAsset: SpitchLowestPath, }, { - id: 'western-slope', - level: '중급', - name: '웨스턴슬로프', - Element: WesternSlopePath, - isOpen: true, + id: 77, + PathAsset: WesternSlopePath, }, { - id: 'sundown-slope', - level: '중급', - name: '썬다운슬로프', - Element: SundownSlopePath, - webcamId: 'soyokgihang-sundown', - isOpen: true, + id: 78, + PathAsset: SundownSlopePath, }, { - id: 'silkroad', - level: '중급', - name: '실크로드', - Element: SilkroadPath, - webcamId: 'seolcheonbong-summit', - isOpen: true, + id: 79, + PathAsset: SilkroadPath, }, { - id: 'rookiehill-slope', - level: '중급', - name: '루키힐슬로프', - Element: RookiehillSlopePath, - isOpen: true, + id: 80, + PathAsset: RookiehillSlopePath, }, { - id: 'turbo-slope', - level: '중급', - name: '터보슬로프', - Element: TurboSlopePath, - webcamId: 'soyokgihang-sundown', - isOpen: true, + id: 81, + PathAsset: TurboSlopePath, }, { - id: 'connection-slope', - level: '중급', - name: '커넥션슬로프', - Element: ConnectionSlopePath, - isOpen: true, + id: 82, + PathAsset: ConnectionSlopePath, }, { - id: 'minuet', - level: '상급', - name: '미뉴에트', - Element: MinuetPath, - webcamId: 'mozart-minuet', - isOpen: true, + id: 83, + PathAsset: MinuetPath, }, { - id: 'freeway', - level: '상급', - name: '프리웨이', - Element: FreewayPath, - webcamId: 'heidi-house', - isOpen: true, + id: 84, + PathAsset: FreewayPath, }, { - id: 'yamaga-slope', - level: '상급', - name: '야마가슬로프', - Element: YamagaSlopePath, - webcamId: 'heidi-house', - isOpen: true, + id: 85, + PathAsset: YamagaSlopePath, }, { - id: 'panorama', - level: '상급', - name: '파노라마', - Element: PanoramaPath, - isOpen: true, + id: 86, + PathAsset: PanoramaPath, }, { - id: 'raiders-lowest', - level: '상급', - name: '레이더스 하단', - Element: RaidersLowestPath, - isOpen: true, + id: 87, + PathAsset: RaidersLowestPath, }, { - id: 'mozart', - level: '상급', - name: '모차르트', - Element: MozartPath, - webcamId: 'mozart-minuet', - isOpen: true, + id: 88, + PathAsset: MozartPath, }, { - id: 'waltz-slope', - level: '상급', - name: '왈츠슬로프', - Element: WaltzSlopePath, - isOpen: true, + id: 89, + PathAsset: WaltzSlopePath, }, { - id: 'allegro', - level: '상급', - name: '알레그로', - Element: AllegroPath, - webcamId: 'seolcheon-top-slope', - isOpen: true, + id: 90, + PathAsset: AllegroPath, }, { - id: 'raiders-highest', - level: '최상급', - name: '레이더스 상단', - Element: RaidersHighestPath, - webcamId: 'mansunbong-summit', - isOpen: true, + id: 91, + PathAsset: RaidersHighestPath, }, { - id: 'polka-slope', - level: '최상급', - name: '폴카슬로프', - Element: PolkaSlopePath, - webcamId: 'seolcheon-top-slope', - isOpen: true, + id: 92, + PathAsset: PolkaSlopePath, }, { - id: 'cadenza-slope', - level: '최상급', - name: '카덴자슬로프', - Element: CadenzaSlopePath, - webcamId: 'seolcheon-top-slope', - isOpen: true, - }, - { - id: 'shortcut-slope', - level: '초급', - name: '쇼트컷슬로프', - Element: ShortcutSlopePath, - isOpen: true, - }, - { - id: 'spitch-slope', - level: '초급', - name: '스피츠슬로프', - Element: SpitchSlopePath, - isOpen: true, - }, - { - id: 'flamingo', - level: '초급', - name: '플라밍고', - Element: FlamingoPath, - isOpen: true, - }, - { - id: 'moderato', - level: '초급', - name: '모데라토', - Element: ModeratoPath, - isOpen: true, - }, - { - id: 'r-gardner-slope', - level: '초급', - name: 'R.가드너슬로프', - Element: RGardnerSlopePath, - isOpen: true, - }, - { - id: 'freeway2', - level: '초급', - name: '프리웨이2', - Element: Freeway2Path, - isOpen: true, - }, - { - id: 'rusutsu-slope', - level: '초급', - name: '루스츠슬로프', - Element: RusutsuSlopePath, - isOpen: true, + id: 93, + PathAsset: CadenzaSlopePath, }, + // { + // id: 'shortcut-slope', + // PathAsset: ShortcutSlopePath, + // }, + // { + // id: 'spitch-slope', + // PathAsset: SpitchSlopePath, + // }, + // { + // id: 'flamingo', + // PathAsset: FlamingoPath, + // }, + // { + // id: 'moderato', + // PathAsset: ModeratoPath, + // }, + // { + // id: 'r-gardner-slope', + // PathAsset: RGardnerSlopePath, + // }, + // { + // id: 'freeway2', + // PathAsset: Freeway2Path, + // }, + // { + // id: 'rusutsu-slope', + // PathAsset: RusutsuSlopePath, + // }, ], webcams: [ { - id: 'mansun-house', - name: '만선 하우스', + id: 1, position: { - top: 'top-[78%]', - left: 'left-[47%]', + top: 'top-[16%]', + left: 'left-[23%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam01.stream/playlist.m3u8', scale: 2, }, { - id: 'heidi-house', - name: '하이디 하우스', + id: 2, position: { - top: 'top-[45%]', - left: 'left-[70%]', + top: 'top-[12%]', + left: 'left-[37%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam03.stream/playlist.m3u8', scale: 2, }, { - id: 'seolcheon-house', - name: '설천 하우스', + id: 3, position: { - top: 'top-[74%]', - left: 'left-[28%]', + top: 'top-[30%]', + left: 'left-[27%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam05.stream/playlist.m3u8', scale: 2, }, { - id: 'soyokgihang-sundown', - name: '서역기행, 썬다운', + id: 4, position: { - top: 'top-[65%]', - left: 'left-[68%]', + top: 'top-[32%]', + left: 'left-[51%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam04.stream/playlist.m3u8', scale: 2, }, { - id: 'seolcheonbong-summit', - name: '설천봉 정상', + id: 5, position: { - top: 'top-[12%]', - left: 'left-[37%]', + top: 'top-[45%]', + left: 'left-[70%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam07.stream/playlist.m3u8', scale: 2, }, { - id: 'mozart-minuet', - name: '모차르트, 미뉴에트', + id: 6, position: { - top: 'top-[30%]', - left: 'left-[27%]', + top: 'top-[65%]', + left: 'left-[68%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam08.stream/playlist.m3u8', scale: 2, }, { - id: 'seolcheon-top-slope', - name: '설천상단 슬로프', + id: 7, position: { - top: 'top-[16%]', - left: 'left-[23%]', + top: 'top-[78%]', + left: 'left-[47%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam06.stream/playlist.m3u8', scale: 2, }, { - id: 'mansunbong-summit', - name: '만선봉 정상', + id: 8, position: { - top: 'top-[32%]', - left: 'left-[51%]', + top: 'top-[74%]', + left: 'left-[28%]', }, - src: '/api/webcam?url=http://muju.live.cdn.cloudn.co.kr/mujuresort/_definst_/cam02.stream/playlist.m3u8', scale: 2, }, ], diff --git a/src/entities/slope/model/resorts/o2.tsx b/src/entities/slope/model/resorts/o2.tsx index 35f6019..4a236b3 100644 --- a/src/entities/slope/model/resorts/o2.tsx +++ b/src/entities/slope/model/resorts/o2.tsx @@ -20,136 +20,85 @@ export const O2: ResortConstant = { MapComponent: MapImage, slopes: [ { - id: 'dream-slope1', - level: '초급', - name: '드림슬로프 1', - Element: DreamSlope1Path, - webcamId: 'dream1', - isOpen: true, + id: 132, + PathAsset: DreamSlope1Path, }, { - id: 'dream-slope2', - level: '초급', - name: '드림슬로프 2', - Element: DreamSlope2Path, - isOpen: true, + id: 133, + PathAsset: DreamSlope2Path, }, { - id: 'head-slope', - level: '중급', - name: '헤드슬로프', - Element: HeadSlopePath, - isOpen: true, + id: 134, + PathAsset: HeadSlopePath, }, { - id: 'happy-slope', - level: '중급', - name: '해피슬로프', - Element: HappySlopePath, - webcamId: 'peak1', - isOpen: true, + id: 135, + PathAsset: HappySlopePath, }, { - id: 'glory-slope1', - level: '상급', - name: '글로리슬로프 1', - Element: GlorySlope1Path, - isOpen: true, + id: 136, + PathAsset: GlorySlope1Path, }, { - id: 'glory-slope2', - level: '상급', - name: '글로리슬로프 2', - Element: GlorySlope2Path, - isOpen: true, + id: 137, + PathAsset: GlorySlope2Path, }, { - id: 'glory-slope3', - level: '상급', - name: '글로리슬로프 3', - Element: GlorySlope3Path, - webcamId: 'peak1', - isOpen: true, + id: 138, + PathAsset: GlorySlope3Path, }, { - id: 'fashion-slope1', - level: '최상급', - name: '패션슬로프 1', - Element: FashionSlope1Path, - webcamId: 'peak1', - isOpen: true, + id: 139, + PathAsset: FashionSlope1Path, }, { - id: 'fashion-slope2', - level: '최상급', - name: '패션슬로프 2', - Element: FashionSlope2Path, - isOpen: true, + id: 140, + PathAsset: FashionSlope2Path, }, { - id: 'challenge-slope1', - level: '최상급', - name: '챌린지슬로프 1', - Element: ChallengeSlope1Path, - webcamId: 'peak2', - isOpen: true, + id: 141, + PathAsset: ChallengeSlope1Path, }, { - id: 'challenge-slope2', - level: '최상급', - name: '챌린지슬로프 2', - Element: ChallengeSlope2Path, - webcamId: 'peak2', - isOpen: true, + id: 142, + PathAsset: ChallengeSlope2Path, }, { - id: 'challenge-slope3', - level: '최상급', - name: '챌린지슬로프 3', - Element: ChallengeSlope3Path, - webcamId: 'peak2', - isOpen: true, + id: 143, + PathAsset: ChallengeSlope3Path, }, { - id: 'half-pipe', - level: '초급', - name: '하프파이프', - Element: HalfPipePath, - webcamId: 'ski-house', - isOpen: true, + id: 144, + PathAsset: HalfPipePath, }, ], webcams: [ { - id: 'dream1', - name: '드림1', + id: 1, position: { - top: 'top-[80%]', - left: 'left-[48%]', + top: 'top-[5%]', + left: 'left-[75%]', }, scale: 1, }, { - id: 'peak1', - name: '으뜸마루', + id: 2, position: { - top: 'top-[5%]', - left: 'left-[75%]', + top: 'top-[23%]', + left: 'left-[46%]', }, scale: 1, }, { - id: 'peak2', - name: '버금마루', + id: 3, position: { - top: 'top-[23%]', - left: 'left-[46%]', + top: 'top-[80%]', + left: 'left-[48%]', }, scale: 1, }, { - id: 'ski-house', - name: '오투 스키하우스', + id: 4, position: { top: 'top-[76%]', left: 'left-[14%]', diff --git a/src/entities/slope/model/resorts/phoenix.tsx b/src/entities/slope/model/resorts/phoenix.tsx index 2044a10..6a54731 100644 --- a/src/entities/slope/model/resorts/phoenix.tsx +++ b/src/entities/slope/model/resorts/phoenix.tsx @@ -22,178 +22,117 @@ export const PHOENIX: ResortConstant = { MapComponent: MapImage, slopes: [ { - id: 'sparrow', - level: '초급', - name: '스패로우', - Element: SparrowPath, - webcamId: 'sparrow', - isOpen: true, + id: 59, + PathAsset: SparrowPath, }, { - id: 'penguin-slope', - level: '초급', - name: '펭귄 슬로프', - Element: PenguinSlopePath, - webcamId: 'penguin-slope', - isOpen: true, + id: 60, + PathAsset: PenguinSlopePath, }, { - id: 'hawk-slope1', - level: '초급', - name: '호크 슬로프 1', - Element: HawkSlope1Path, - isOpen: true, + id: 61, + PathAsset: HawkSlope1Path, }, { - id: 'kiwi-slope', - level: '중급', - name: '키위 슬로프', - Element: KiwiSlopePath, - webcamId: 'ski-base', - isOpen: true, + id: 62, + PathAsset: KiwiSlopePath, }, { - id: 'panorama', - level: '중급', - name: '파노라마', - Element: PanoramaPath, - webcamId: 'panorama', - isOpen: true, + id: 63, + PathAsset: PanoramaPath, }, { - id: 'valley-slope', - level: '중급', - name: '밸리 슬로프', - Element: ValleySlopePath, - webcamId: 'montblanc-peak', - isOpen: true, + id: 64, + PathAsset: ValleySlopePath, }, { - id: 'hawk-slope2', - level: '중급', - name: '호크 슬로프 2', - Element: HawkSlope2Path, - isOpen: true, + id: 65, + PathAsset: HawkSlope2Path, }, { - id: 'duke-slope', - level: '중급', - name: '듀크 슬로프', - Element: DukeSlopePath, - webcamId: 'bulsae-maru-zone', - isOpen: true, + id: 66, + PathAsset: DukeSlopePath, }, { - id: 'slope-style', - level: '중급', - name: '슬로프 스타일', - Element: SlopeStylePath, - webcamId: 'penguin-slope', - isOpen: true, + id: 67, + PathAsset: SlopeStylePath, }, { - id: 'champion-slope', - level: '상급', - name: '챔피언 슬로프', - Element: ChampionSlopePath, - webcamId: 'champion', - isOpen: true, + id: 68, + PathAsset: ChampionSlopePath, }, { - id: 'fantasy-slope', - level: '상급', - name: '환타지 슬로프', - Element: FantasySlopePath, - isOpen: true, + id: 69, + PathAsset: FantasySlopePath, }, { - id: 'diggy-slope', - level: '최상급', - name: '디지 슬로프', - Element: DiggySlopePath, - webcamId: 'montblanc-peak', - isOpen: true, + id: 70, + PathAsset: DiggySlopePath, }, { - id: 'mogul-slope', - level: '최상급', - name: '모글 슬로프', - Element: MogulSlopePath, - isOpen: true, + id: 71, + PathAsset: MogulSlopePath, }, { - id: 'paradise', - level: '최상급', - name: '파라다이스', - Element: ParadisePath, - isOpen: true, + id: 72, + PathAsset: ParadisePath, }, { - id: 'extreme-park', - level: '초급', - name: '익스트림 파크', - Element: ExtremeParkPath, - isOpen: true, + id: 73, + PathAsset: ExtremeParkPath, }, ], webcams: [ { - id: 'sparrow', - name: '스패로우', + id: 1, position: { - top: 'top-[45%]', - left: 'left-[87%]', + top: 'top-[83%]', + left: 'left-[79%]', }, scale: 1, }, { - id: 'penguin-slope', - name: '펭귄 슬로프', + id: 2, position: { - top: 'top-[79%]', - left: 'left-[43%]', + top: 'top-[31%]', + left: 'left-[9%]', }, scale: 1, }, { - id: 'ski-base', - name: '스키베이스', + id: 3, position: { - top: 'top-[83%]', - left: 'left-[79%]', + top: 'top-[79%]', + left: 'left-[43%]', }, scale: 1, }, { - id: 'bulsae-maru-zone', - name: '불새마루존', + id: 4, position: { - top: 'top-[31%]', - left: 'left-[9%]', + top: 'top-[15%]', + left: 'left-[88%]', }, scale: 1, }, { - id: 'panorama', - name: '파노라마', + id: 5, position: { - top: 'top-[15%]', - left: 'left-[88%]', + top: 'top-[7%]', + left: 'left-[53%]', }, scale: 1, }, { - id: 'montblanc-peak', - name: '몽블랑 정상', + id: 6, position: { - top: 'top-[7%]', - left: 'left-[53%]', + top: 'top-[45%]', + left: 'left-[87%]', }, scale: 1, }, { - id: 'champion', - name: '챔피온', + id: 7, position: { top: 'top-[26%]', left: 'left-[66%]', diff --git a/src/entities/slope/model/resorts/vivaldipark.tsx b/src/entities/slope/model/resorts/vivaldipark.tsx index ee33637..077d733 100644 --- a/src/entities/slope/model/resorts/vivaldipark.tsx +++ b/src/entities/slope/model/resorts/vivaldipark.tsx @@ -16,134 +16,93 @@ export const VIVALDIPARK: ResortConstant = { MapComponent: VivaldiparkMap, slopes: [ { - id: 'ballad-slop', - level: '초급', - name: '발라드슬로프', - Element: BalladSlopPath, - webcamId: 'ballad-webcam', - isOpen: true, + id: 122, + PathAsset: BalladSlopPath, }, { - id: 'blues-slop', - level: '초급', - name: '블루스슬로프', - Element: BluesSlopPath, - webcamId: 'blues-webcam', - isOpen: true, + id: 123, + PathAsset: BluesSlopPath, }, { - id: 'hiphop-slop', - level: '중상급', - name: '힙합슬로프', - Element: HiphopSlopPath, - webcamId: 'hiphop-webcam', - isOpen: true, + id: 124, + PathAsset: HiphopSlopPath, }, { - id: 'classic-slop', - level: '중상급', - name: '클래식슬로프', - Element: ClassicSlopPath, - webcamId: 'classic-webcam', - isOpen: true, + id: 125, + PathAsset: ClassicSlopPath, }, { - id: 'reggae-slop', - level: '중급', - name: '레게슬로프', - Element: ReggaeSlopPath, - isOpen: true, + id: 126, + PathAsset: ReggaeSlopPath, }, { - id: 'jazz-slop', - level: '중급', - name: '재즈슬로프', - Element: JazzSlopPath, - webcamId: 'jazz-webcam', - isOpen: true, + id: 127, + PathAsset: JazzSlopPath, }, { - id: 'funky-slop', - level: '상급', - name: '펑키슬로프', - Element: FunkySlopPath, - webcamId: 'funky-webcam', - isOpen: true, + id: 128, + PathAsset: FunkySlopPath, }, { - id: 'techno-slop', - level: '상급', - name: '테크노슬로프', - Element: TechnoSlopPath, - webcamId: 'techno-bottom', - isOpen: true, + id: 129, + PathAsset: TechnoSlopPath, }, { - id: 'rock-slop', - level: '최상급', - name: '락슬로프', - Element: RockSlopPath, - isOpen: true, + id: 130, + PathAsset: RockSlopPath, }, ], webcams: [ { - id: 'ballad-webcam', - name: '발라드', + id: 1, position: { - top: 'top-[56%]', - left: 'left-[41%]', + top: 'top-[14%]', + left: 'left-[37%]', }, scale: 1, }, { - id: 'blues-webcam', - name: '블루스', + id: 2, position: { - top: 'top-[62%]', - left: 'left-[77%]', + top: 'top-[24%]', + left: 'left-[48%]', }, scale: 1, }, { - id: 'hiphop-webcam', - name: '힙합', + id: 3, position: { - top: 'top-[34%]', - left: 'left-[55%]', + top: 'top-[30%]', + left: 'left-[30%]', }, scale: 1, }, { - id: 'classic-webcam', - name: '클래식', + id: 4, position: { - top: 'top-[30%]', - left: 'left-[30%]', + top: 'top-[34%]', + left: 'left-[55%]', }, scale: 1, }, { - id: 'jazz-webcam', - name: '재즈', + id: 5, position: { - top: 'top-[62%]', - left: 'left-[21%]', + top: 'top-[44%]', + left: 'left-[46%]', }, scale: 1, }, { - id: 'funky-webcam', - name: '펑키', + id: 6, position: { - top: 'top-[44%]', - left: 'left-[46%]', + top: 'top-[56%]', + left: 'left-[41%]', }, scale: 1, }, { - id: 'techno-bottom', - name: '테크노하단', + id: 7, position: { top: 'top-[64%]', left: 'left-[51%]', @@ -151,29 +110,26 @@ export const VIVALDIPARK: ResortConstant = { scale: 1, }, { - id: 'slope-view', - name: '슬로프 전경', + id: 8, position: { - top: 'top-[76%]', - left: 'left-[45%]', + top: 'top-[62%]', + left: 'left-[21%]', }, scale: 1, }, { - id: 'skiword-top', - name: '스키월드 정상', + id: 9, position: { - top: 'top-[14%]', - left: 'left-[37%]', + top: 'top-[62%]', + left: 'left-[77%]', }, scale: 1, }, { - id: 'techno-top', - name: '테크노 상단', + id: 10, position: { - top: 'top-[24%]', - left: 'left-[48%]', + top: 'top-[76%]', + left: 'left-[45%]', }, scale: 1, }, diff --git a/src/entities/slope/model/resorts/wellihilli.tsx b/src/entities/slope/model/resorts/wellihilli.tsx index 4088346..d7e2ca4 100644 --- a/src/entities/slope/model/resorts/wellihilli.tsx +++ b/src/entities/slope/model/resorts/wellihilli.tsx @@ -13,8 +13,8 @@ import ChallengeSlope4Path from '../image/wellihilli/challenge-slope4-path'; import ChallengeSlope5Path from '../image/wellihilli/challenge-slope5-path'; import DeltaSlopePlusPath from '../image/wellihilli/delta-slope-plus-path'; import DeltaSlope1Path from '../image/wellihilli/delta-slope1-path'; -import DeltaSlope2Path from '../image/wellihilli/delta-slope2-path'; -import EchoSlopePlusPath from '../image/wellihilli/echo-slope-plus-path'; +// import DeltaSlope2Path from '../image/wellihilli/delta-slope2-path'; +// import EchoSlopePlusPath from '../image/wellihilli/echo-slope-plus-path'; import EchoSlope1Path from '../image/wellihilli/echo-slope1-path'; import EchoSlope2Path from '../image/wellihilli/echo-slope2-path'; import EchoSlope3Path from '../image/wellihilli/echo-slope3-path'; @@ -27,202 +27,125 @@ export const WELLIHILLI: ResortConstant = { MapComponent: WellihilliMap, slopes: [ { - id: 'alpha-slope1', - level: '초급', - name: '알파슬로프 1', - Element: AlphaSlope1Path, - webcamId: 'a1/a3-slope', - isOpen: true, + id: 94, + PathAsset: AlphaSlope1Path, }, { - id: 'alpha-slope2', - level: '초급', - name: '알파슬로프 2', - Element: AlphaSlope2Path, - webcamId: 'outdoor-square', - isOpen: true, + id: 95, + PathAsset: AlphaSlope2Path, }, { - id: 'alpha-slope3', - level: '초급', - name: '알파슬로프 3', - Element: AlphaSlope3Path, - webcamId: 'outdoor-square', - isOpen: true, + id: 96, + PathAsset: AlphaSlope3Path, }, { - id: 'bravo-slope1', - level: '중급', - name: '브라보슬로프 1', - Element: BravoSlope1Path, - isOpen: true, + id: 97, + PathAsset: BravoSlope1Path, }, { - id: 'bravo-slope2', - level: '중급', - name: '브라보슬로프 2', - Element: BravoSlope2Path, - isOpen: true, + id: 98, + PathAsset: BravoSlope2Path, }, { - id: 'delta-slope1', - level: '초급', - name: '델타슬로프 1', - Element: DeltaSlope1Path, - webcamId: 'family-slope', - isOpen: true, + id: 99, + PathAsset: DeltaSlope1Path, }, + // { + // id: 'delta-slope2', + // PathAsset: DeltaSlope2Path, + // }, { - id: 'delta-slope2', - level: '초급', - name: '델타슬로프 2', - Element: DeltaSlope2Path, - webcamId: 'top-square', - isOpen: true, + id: 100, + PathAsset: DeltaSlopePlusPath, }, { - id: 'delta-slope-plus', - level: '초급', - name: '델타슬로프 +', - Element: DeltaSlopePlusPath, - isOpen: true, + id: 101, + PathAsset: EchoSlope1Path, }, { - id: 'echo-slope1', - level: '최상급', - name: '에코슬로프 1', - Element: EchoSlope1Path, - isOpen: true, + id: 102, + PathAsset: EchoSlope2Path, }, { - id: 'echo-slope2', - level: '상급', - name: '에코슬로프 2', - Element: EchoSlope2Path, - isOpen: true, + id: 103, + PathAsset: EchoSlope3Path, }, + // { + // id: 'echo-slope-plus', + // PathAsset: EchoSlopePlusPath, + // }, { - id: 'echo-slope3', - level: '최상급', - name: '에코슬로프 3', - Element: EchoSlope3Path, - isOpen: true, + id: 104, + PathAsset: ChallengeSlope1Path, }, { - id: 'echo-slope-plus', - level: '최상급', - name: '에코슬로프 +', - Element: EchoSlopePlusPath, - isOpen: true, + id: 105, + PathAsset: ChallengeSlope2Path, }, { - id: 'challenge-slope1', - level: '상급', - name: '첼린지슬로프 1', - Element: ChallengeSlope1Path, - isOpen: true, + id: 106, + PathAsset: ChallengeSlope3Path, }, { - id: 'challenge-slope2', - level: '상급', - name: '첼린지슬로프 2', - Element: ChallengeSlope2Path, - isOpen: true, + id: 107, + PathAsset: ChallengeSlope4Path, }, { - id: 'challenge-slope3', - level: '최상급', - name: '첼린지슬로프 3', - Element: ChallengeSlope3Path, - isOpen: true, + id: 108, + PathAsset: ChallengeSlope5Path, }, { - id: 'challenge-slope4', - level: '상급', - name: '첼린지슬로프 4', - Element: ChallengeSlope4Path, - isOpen: true, + id: 109, + PathAsset: StarExpress1Path, }, { - id: 'challenge-slope5', - level: '상급', - name: '첼린지슬로프 5', - Element: ChallengeSlope5Path, - isOpen: true, + id: 110, + PathAsset: StarExpress2Path, }, { - id: 'star-express1', - level: '중급', - name: '스타 익스프레스1', - Element: StarExpress1Path, - isOpen: true, - }, - { - id: 'star-express2', - level: '초급', - name: '스타 익스프레스2', - Element: StarExpress2Path, - webcamId: 'top-square', - isOpen: true, - }, - { - id: 'half-pipe', - level: '초급', - name: '하프파이프', - Element: HalfPipePath, - webcamId: 'half-pipe', - isOpen: true, + id: 111, + PathAsset: HalfPipePath, }, ], webcams: [ { - id: 'a1/a3-slope', - name: 'A1/A3 슬로프', + id: 1, position: { - top: 'top-[62%]', - left: 'left-[8%]', + top: 'top-[4%]', + left: 'left-[56%]', }, - src: '/api/webcam?url=https://live.wellihillipark.com/wellihillipark/_definst_/cam07.stream/playlist.m3u8', scale: 1, }, { - id: 'outdoor-square', - name: '야외광장', + id: 2, position: { - top: 'top-[73%]', - left: 'left-[19%]', + top: 'top-[81%]', + left: 'left-[31%]', }, - src: '/api/webcam?url=https://live.wellihillipark.com/wellihillipark/_definst_/cam06.stream/playlist.m3u8', scale: 1, }, { - id: 'family-slope', - name: '패밀리슬로프', + id: 3, position: { top: 'top-[85%]', left: 'left-[39%]', }, - src: '/api/webcam?url=https://live.wellihillipark.com/wellihillipark/_definst_/cam05.stream/playlist.m3u8', scale: 1, }, { - id: 'top-square', - name: '정상광장', + id: 4, position: { - top: 'top-[4%]', - left: 'left-[56%]', + top: 'top-[73%]', + left: 'left-[19%]', }, - src: '/api/webcam?url=https://live.wellihillipark.com/wellihillipark/_definst_/cam03.stream/playlist.m3u8', scale: 1, }, { - id: 'half-pipe', - name: '하프파이프', + id: 5, position: { - top: 'top-[81%]', - left: 'left-[31%]', + top: 'top-[62%]', + left: 'left-[8%]', }, - src: '/api/webcam?url=https://live.wellihillipark.com/wellihillipark/_definst_/cam04.stream/playlist.m3u8', scale: 1, }, ], diff --git a/src/entities/slope/model/resorts/yongpyong.tsx b/src/entities/slope/model/resorts/yongpyong.tsx index 47f00da..77228eb 100644 --- a/src/entities/slope/model/resorts/yongpyong.tsx +++ b/src/entities/slope/model/resorts/yongpyong.tsx @@ -19,8 +19,8 @@ import Rainbow4Path from '../image/yongpyong/rainbow4-path'; import RedParadisePath from '../image/yongpyong/red-paradise-path'; import RedSlopePath from '../image/yongpyong/red-slope-path'; import SilverParadisePath from '../image/yongpyong/silver-paradise-path'; -import SilverSlopePath from '../image/yongpyong/silver-slope-path'; -import SummitLandTheGreenPath from '../image/yongpyong/summit-land-the-green-path'; +// import SilverSlopePath from '../image/yongpyong/silver-slope-path'; +// import SummitLandTheGreenPath from '../image/yongpyong/summit-land-the-green-path'; import YellowSlopePath from '../image/yongpyong/yellow-slope-path'; import type { ResortConstant } from '../model'; @@ -28,259 +28,168 @@ export const YONGPYONG: ResortConstant = { MapComponent: MapImage, slopes: [ { - id: 'gold-valley', - level: '상급', - name: '골드 밸리', - Element: GoldValleyPath, - webcamId: 'gold-slope-foreground', - isOpen: true, + id: 40, + PathAsset: GoldValleyPath, }, { - id: 'gold-paradise', - level: '중급', - name: '골드 파라다이스', - Element: GoldParadisePath, - isOpen: true, + id: 41, + PathAsset: GoldParadisePath, }, { - id: 'new-gold-slope', - level: '상급', - name: '뉴골드슬로프', - Element: NewGoldSlopePath, - webcamId: 'gold-slope-foreground', - isOpen: true, + id: 42, + PathAsset: NewGoldSlopePath, }, { - id: 'gold-fantastic', - level: '상급', - name: '골드 환타스틱', - Element: GoldFantasticPath, - webcamId: 'gold-slope-foreground', - isOpen: true, + id: 43, + PathAsset: GoldFantasticPath, }, { - id: 'red-paradise', - level: '중급', - name: '레드 파라다이스', - Element: RedParadisePath, - webcamId: 'red-slope', - isOpen: true, + id: 44, + PathAsset: RedParadisePath, }, { - id: 'red-slope', - level: '최상급', - name: '레드슬로프', - Element: RedSlopePath, - isOpen: true, + id: 45, + PathAsset: RedSlopePath, }, { - id: 'new-red-slope', - level: '상급', - name: '뉴레드슬로프', - Element: NewRedSlopePath, - webcamId: 'red-slope', - isOpen: true, + id: 46, + PathAsset: NewRedSlopePath, }, { - id: 'blue-slope', - level: '상급', - name: '블루슬로프', - Element: BlueSlopePath, - isOpen: true, + id: 47, + PathAsset: BlueSlopePath, }, { - id: 'pink-slope', - level: '중급', - name: '핑크슬로프', - Element: PinkSlopePath, - webcamId: 'pink-slope', - isOpen: true, + id: 48, + PathAsset: PinkSlopePath, }, { - id: 'yellow-slope', - level: '초급', - name: '옐로우슬로프', - Element: YellowSlopePath, - isOpen: true, + id: 49, + PathAsset: YellowSlopePath, }, { - id: 'new-yellow-slope', - level: '초급', - name: '뉴 옐로우 슬로프', - Element: NewYellowSlopePath, - webcamId: 'yellow-slope', - isOpen: true, + id: 50, + PathAsset: NewYellowSlopePath, }, + // { + // id: 'silver-slope', + // PathAsset: SilverSlopePath, + // }, { - id: 'silver-slope', - level: '중급', - name: '실버 슬로프', - Element: SilverSlopePath, - isOpen: true, + id: 51, + PathAsset: SilverParadisePath, }, { - id: 'silver-paradise', - level: '중급', - name: '실버 파라다이스', - Element: SilverParadisePath, - isOpen: true, + id: 52, + PathAsset: RainbowParadisePath, }, { - id: 'rainbow-paradise', - level: '중급', - name: '레인보우 파라다이스', - Element: RainbowParadisePath, - webcamId: 'rainbow-top', - isOpen: true, + id: 53, + PathAsset: Rainbow1Path, }, { - id: 'rainbow1', - level: '최상급', - name: '레인보우 1', - Element: Rainbow1Path, - webcamId: 'rainbow-foreground', - isOpen: true, + id: 54, + PathAsset: Rainbow2Path, }, { - id: 'rainbow2', - level: '최상급', - name: '레인보우 2', - Element: Rainbow2Path, - webcamId: 'rainbow-foreground', - isOpen: true, + id: 55, + PathAsset: Rainbow3Path, }, { - id: 'rainbow3', - level: '최상급', - name: '레인보우 3', - Element: Rainbow3Path, - webcamId: 'rainbow-foreground', - isOpen: true, + id: 56, + PathAsset: Rainbow4Path, }, { - id: 'rainbow4', - level: '상급', - name: '레인보우 4', - Element: Rainbow4Path, - webcamId: 'rainbow-foreground', - isOpen: true, + id: 57, + PathAsset: MegaGreenPath, }, { - id: 'mega-green', - level: '중급', - name: '메가 그린', - Element: MegaGreenPath, - webcamId: 'mega-green-slope', - isOpen: true, - }, - { - id: 'dragon-park', - level: '중급', - name: '드래곤 파크', - Element: DragonParkPath, - isOpen: true, - }, - { - id: 'summit-land-the-green', - level: '중급', - name: '서밋랜드 더 그린', - Element: SummitLandTheGreenPath, - isOpen: false, + id: 58, + PathAsset: DragonParkPath, }, + // { + // id: 'summit-land-the-green', + // PathAsset: SummitLandTheGreenPath, + // }, ], webcams: [ { - id: 'gold-slope-foreground', - name: '골드 슬로프 전경', + id: 1, position: { - top: 'top-[56%]', - left: 'left-[17%]', + top: 'top-[2%]', + left: 'left-[61%]', }, - src: '/api/webcam?url=https://live.yongpyong.co.kr/Ycam1/cam15.stream/chunklist.m3u8', scale: 2, }, { - id: 'red-slope', - name: '레드 슬로프', + id: 2, position: { - top: 'top-[57%]', - left: 'left-[29%]', + top: 'top-[26%]', + left: 'left-[30%]', }, - src: '/api/webcam?url=https://live.yongpyong.co.kr/Ycam1/cam03.stream/chunklist.m3u8', scale: 2, }, { - id: 'pink-slope', - name: '핑크 슬로프', + id: 3, position: { - top: 'top-[64%]', - left: 'left-[33%]', + top: 'top-[41%]', + left: 'left-[79%]', }, scale: 2, }, { - id: 'yellow-slope', - name: '옐로우 슬로프', + id: 4, position: { - top: 'top-[71%]', - left: 'left-[37%]', + top: 'top-[56%]', + left: 'left-[17%]', }, scale: 2, }, { - id: 'rainbow-top', - name: '레인보우 정상', + id: 5, position: { - top: 'top-[2%]', - left: 'left-[61%]', + top: 'top-[59%]', + left: 'left-[56%]', }, - src: '/api/webcam?url=https://live.yongpyong.co.kr/Ycam1/cam05.stream/chunklist.m3u8', scale: 2, }, { - id: 'rainbow-foreground', - name: '레인보우 전경', + id: 6, position: { - top: 'top-[41%]', - left: 'left-[79%]', + top: 'top-[57%]', + left: 'left-[29%]', }, - src: '/api/webcam?url=https://live.yongpyong.co.kr/Ycam1/cam10.stream/chunklist.m3u8', scale: 2, }, { - id: 'mega-green-slope', - name: '메가 그린 슬로프', + id: 7, position: { - top: 'top-[59%]', - left: 'left-[56%]', + top: 'top-[64%]', + left: 'left-[33%]', }, - src: '/api/webcam?url=https://live.yongpyong.co.kr/Ycam1/cam07.stream/chunklist.m3u8', scale: 2, }, { - id: 'base-foreground', - name: '베이스 전경', + id: 8, position: { - top: 'top-[84%]', - left: 'left-[34%]', + top: 'top-[71%]', + left: 'left-[37%]', }, scale: 2, }, { - id: 'access-road', - name: '용평 진입로', + id: 9, position: { - top: 'top-[86%]', - left: 'left-[26%]', + top: 'top-[84%]', + left: 'left-[34%]', }, scale: 2, }, { - id: 'slope-top', - name: '슬로프 정상', + id: 10, position: { - top: 'top-[26%]', - left: 'left-[30%]', + top: 'top-[86%]', + left: 'left-[26%]', }, scale: 2, }, diff --git a/src/features/slope/hooks/useSlopeStore.ts b/src/features/slope/hooks/useSlopeStore.ts index 0dbfc47..38ab527 100644 --- a/src/features/slope/hooks/useSlopeStore.ts +++ b/src/features/slope/hooks/useSlopeStore.ts @@ -1,7 +1,7 @@ import { create } from 'zustand'; -type SlopeId = string | null; -type CameraId = string | null | undefined; +type SlopeId = number | null; +type CameraId = number | null | undefined; interface SlopeState { selectedSlope: SlopeId; diff --git a/src/features/slope/ui/slope-camera.tsx b/src/features/slope/ui/slope-camera.tsx index 5ed7004..d7b5430 100644 --- a/src/features/slope/ui/slope-camera.tsx +++ b/src/features/slope/ui/slope-camera.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import { toast } from 'sonner'; -import type { Position, WebcamConstant } from '@/entities/slope/model'; +import type { Position, Webcam } from '@/entities/slope/model'; import ArrowRightIcon from '@/shared/icons/arrow-right'; import NeutralFace from '@/shared/icons/neutral-face'; import { cn } from '@/shared/lib'; @@ -14,17 +14,17 @@ import SlopeVideo from './slope-video'; interface SlopeWebcamProps { isWebview?: boolean; - webcam: WebcamConstant; + webcam: Webcam; webcamScale: number; isOpen: boolean; containerRef: React.RefObject; - onCameraClick: ({ scale, id }: { scale: number; id: string }) => void; - updateCameraPosition: (id: string, position: Position) => void; + onCameraClick: ({ scale, id }: { scale: number; id: number }) => void; + updateCameraPosition: (id: number, position: Position) => void; } const SlopeCamera = ({ isWebview = false, - webcam: { scale, name, position, src, id }, + webcam: { scale, name, position, url, id }, webcamScale, isOpen, containerRef, @@ -47,7 +47,7 @@ const SlopeCamera = ({ const openVideo = () => { setOpenCamera(); - if (!src) { + if (!url) { postAppMessage('선택한 웹캠은 아직 준비중 이에요', isWebview, (message) => toast( <> @@ -88,8 +88,11 @@ const SlopeCamera = ({ {containerRef?.current && selectedCamera.isOpen && selectedCamera.id === id && - src && - createPortal(, containerRef.current)} + url && + createPortal( + , + containerRef.current + )} ); }; diff --git a/src/features/slope/ui/slope-map.tsx b/src/features/slope/ui/slope-map.tsx index 7bc5170..62e6cc0 100644 --- a/src/features/slope/ui/slope-map.tsx +++ b/src/features/slope/ui/slope-map.tsx @@ -2,7 +2,7 @@ import { animated } from '@react-spring/web'; import Image, { type StaticImageData } from 'next/image'; import type { ComponentType } from 'react'; import React, { forwardRef } from 'react'; -import type { Level } from '@/entities/slope/model'; +import type { Slope } from '@/entities/slope/model'; import { cn } from '@/shared/lib'; import type useMapPinch from '../hooks/useMapPinch'; import useSlopeStore from '../hooks/useSlopeStore'; @@ -10,15 +10,7 @@ import useSlopeStore from '../hooks/useSlopeStore'; interface SlopeMapProps { children?: React.ReactNode; MapComponent: ComponentType | StaticImageData; - - slopes: { - id: string; - level: Level; - Element: ComponentType<{ - color?: string; - }>; - }[]; - + slopes: Slope[]; style: ReturnType['style']; } @@ -45,10 +37,12 @@ const SlopeMap = forwardRef( )} {slopes.map((slope) => ( -
- +
diff --git a/src/features/slope/ui/slope-status-list.tsx b/src/features/slope/ui/slope-status-list.tsx index 80b50c5..4ad7c3d 100644 --- a/src/features/slope/ui/slope-status-list.tsx +++ b/src/features/slope/ui/slope-status-list.tsx @@ -14,7 +14,7 @@ interface SlopeStatusListProps { const SlopeStatusList = ({ resortId, slopes }: SlopeStatusListProps) => { const { selectedSlope, setSelectedSlope } = useSlopeStore(); - const handleSlopClick = ({ id }: { id: string }) => { + const handleSlopClick = ({ id }: { id: number }) => { gtag('event', 'details_slope_slope_click', { detail_type: resortId, slope_type: id }); setSelectedSlope(id); }; @@ -45,8 +45,8 @@ const SlopeStatusList = ({ resortId, slopes }: SlopeStatusListProps) => { {slopes?.map((slope) => ( handleSlopClick({ id: slope.name })} + className={cn(selectedSlope === slope.slopeId && 'bg-main-5')} + onClick={() => handleSlopClick({ id: slope.slopeId })} > {slope.name} diff --git a/src/shared/icons/close.tsx b/src/shared/icons/close.tsx index 92ed540..c0f6206 100644 --- a/src/shared/icons/close.tsx +++ b/src/shared/icons/close.tsx @@ -8,19 +8,19 @@ interface CloseIconProps extends SVGProps { const CloseIcon = ({ className, ...args }: CloseIconProps) => { return ( ); diff --git a/src/views/resort-detail/ui/resort-detail-page.tsx b/src/views/resort-detail/ui/resort-detail-page.tsx index f15b745..3702d6f 100644 --- a/src/views/resort-detail/ui/resort-detail-page.tsx +++ b/src/views/resort-detail/ui/resort-detail-page.tsx @@ -17,8 +17,9 @@ import calculateWebcamPosition from '@/features/slope/lib/calculateWebcamPositio import { type ResortInfo, ResortData } from '@/entities/resort'; import { resortApi } from '@/entities/resort'; import { usePostVote } from '@/entities/resort/api/use-post-vote'; +import { slopeApi } from '@/entities/slope'; import { RESORT_DOMAIN } from '@/entities/slope/model'; -import type { Position } from '@/entities/slope/model'; +import type { Position, Slope, Webcam } from '@/entities/slope/model'; import CheckIcon from '@/shared/icons/check'; import { cn } from '@/shared/lib'; @@ -28,21 +29,40 @@ const ResortDetailPage = ({ params }: { params: { resortId: string } }) => { const resort = resortsData?.find((resort) => resort.resortId === +params?.resortId); const { data: voteData } = useQuery(resortApi.resortQueries.vote(+params?.resortId)); const data = RESORT_DOMAIN[resortInfo?.map as keyof typeof RESORT_DOMAIN]; + const { data: slopeRawData } = useQuery(slopeApi.slopeQueries.slope(+params?.resortId)); + const key = ResortData.find((resort) => resort.id === +params?.resortId) + ?.map as keyof typeof RESORT_DOMAIN; + const slopes = slopeRawData?.slopes + .filter((slope) => + RESORT_DOMAIN[key].slopes.find((slopeConstant) => slopeConstant.id === slope.slopeId) + ) + .map((slope) => ({ + ...slope, + ...RESORT_DOMAIN[key].slopes.find((slopeConstant) => slopeConstant.id === slope.slopeId), + })) as Slope[]; + const webcams = slopeRawData?.webcams + .filter((webcam) => + RESORT_DOMAIN[key].webcams.find((webcamConstant) => webcamConstant.id === webcam.number) + ) + .map((webcam) => ({ + ...webcam, + ...RESORT_DOMAIN[key].webcams.find((webcamConstant) => webcamConstant.id === webcam.number), + })) as Webcam[]; const [selectedTab, setSelectedTab] = useState('webcam'); const [showAppDownloadDialog, setShowAppDownloadDialog] = useState(true); const { mutateAsync } = usePostVote(+params?.resortId); const [isPositive, setIsPositive] = useState(true); const [cameraPositions, setCameraPositions] = useState<{ - [key: string]: Position; + [key: number]: Position; }>({}); const { ref, style, api, containerRef } = useMapPinch(); - const updateCameraPosition = useCallback((id: string, position: Position) => { + const updateCameraPosition = useCallback((id: number, position: Position) => { setCameraPositions((prev) => ({ ...prev, [id]: position })); }, []); - const handleFocusSlopCamClick = ({ id }: { id: string }) => { + const handleFocusSlopCamClick = ({ id }: { id: number }) => { const { width, height } = containerRef.current!.getBoundingClientRect(); const { boundedX, boundedY } = calculateWebcamPosition({ containerPosition: { left: 0, top: 0, width, height }, @@ -76,7 +96,7 @@ const ResortDetailPage = ({ params }: { params: { resortId: string } }) => { gtag('event', 'page_view_details', { detail_type: params?.resortId }); }, []); - if (!resortInfo || !resort) return; + if (!resortInfo || !resort || !slopes || !webcams) return; return (
@@ -105,16 +125,16 @@ const ResortDetailPage = ({ params }: { params: { resortId: string } }) => { ref={ref} style={style} containerRef={containerRef} - slopes={data.slopes} - webcams={data.webcams} + slopes={slopes} + webcams={webcams} MapComponent={data.MapComponent} onCameraClick={handleFocusSlopCamClick} updateCameraPosition={updateCameraPosition} />
diff --git a/src/views/slope-status/ui/slope-status-page.tsx b/src/views/slope-status/ui/slope-status-page.tsx index 5d15840..3521345 100644 --- a/src/views/slope-status/ui/slope-status-page.tsx +++ b/src/views/slope-status/ui/slope-status-page.tsx @@ -1,21 +1,37 @@ 'use client'; import { useQuery } from '@tanstack/react-query'; +import { useMemo } from 'react'; import SlopeStatusHeader from '@/widgets/header/ui/slope-status-header'; import useMapPinch from '@/features/slope/hooks/useMapPinch'; import SlopeMap from '@/features/slope/ui/slope-map'; import SlopeStatusList from '@/features/slope/ui/slope-status-list'; import { ResortData } from '@/entities/resort'; import { slopeApi } from '@/entities/slope'; +import type { Slope } from '@/entities/slope/model'; import { RESORT_DOMAIN } from '@/entities/slope/model'; import { cn } from '@/shared/lib'; const SlopeStatusPage = ({ resortId }: { resortId: number }) => { const { ref, style, containerRef } = useMapPinch(); - const { data: slopeData } = useQuery(slopeApi.slopeQueries.slope(resortId ?? 0)); + const { data: slopeRawData } = useQuery(slopeApi.slopeQueries.slope(resortId ?? 0)); const key = ResortData.find((resort) => resort.id === resortId) ?.map as keyof typeof RESORT_DOMAIN; + const slopes = useMemo( + () => + slopeRawData?.slopes + .filter((slope) => + RESORT_DOMAIN[key].slopes.find((slopeConstant) => slopeConstant.id === slope.slopeId) + ) + .map((slope) => ({ + ...slope, + ...RESORT_DOMAIN[key].slopes.find((slopeConstant) => slopeConstant.id === slope.slopeId), + })) as Slope[], + [slopeRawData, key] + ); + + if (!slopes) return; return (
@@ -25,10 +41,10 @@ const SlopeStatusPage = ({ resortId }: { resortId: number }) => { style={style} ref={ref} MapComponent={RESORT_DOMAIN[key].MapComponent} - slopes={RESORT_DOMAIN[key].slopes} + slopes={slopes} /> - +
); }; diff --git a/src/views/webcam/ui/webcam-mobile-map-page.tsx b/src/views/webcam/ui/webcam-mobile-map-page.tsx index 94fcfd2..f196357 100644 --- a/src/views/webcam/ui/webcam-mobile-map-page.tsx +++ b/src/views/webcam/ui/webcam-mobile-map-page.tsx @@ -1,28 +1,47 @@ 'use client'; +import { useQuery } from '@tanstack/react-query'; import React, { useCallback, useState } from 'react'; import { WebcamMap, WebcamSlopeList } from '@/widgets/webcam/ui'; import useMapPinch from '@/features/slope/hooks/useMapPinch'; import calculateWebcamPosition from '@/features/slope/lib/calculateWebcamPosition'; import { ResortData } from '@/entities/resort'; +import { slopeApi } from '@/entities/slope'; +import type { Slope, Webcam } from '@/entities/slope/model'; import { RESORT_DOMAIN, type Position } from '@/entities/slope/model'; import { cn } from '@/shared/lib'; const WebCamMobileMapPage = ({ resortId }: { resortId?: number }) => { - const data = - RESORT_DOMAIN[ - ResortData.find((resort) => resort.id === resortId)?.map as keyof typeof RESORT_DOMAIN - ]; + const { data: slopeRawData } = useQuery(slopeApi.slopeQueries.slope(resortId ?? 0)); + const key = ResortData.find((resort) => resort.id === resortId) + ?.map as keyof typeof RESORT_DOMAIN; + const slopes = slopeRawData?.slopes + .filter((slope) => + RESORT_DOMAIN[key].slopes.find((slopeConstant) => slopeConstant.id === slope.slopeId) + ) + .map((slope) => ({ + ...slope, + ...RESORT_DOMAIN[key].slopes.find((slopeConstant) => slopeConstant.id === slope.slopeId), + })) as Slope[]; + const webcams = slopeRawData?.webcams + .filter((webcam) => + RESORT_DOMAIN[key].webcams.find((webcamConstant) => webcamConstant.id === webcam.number) + ) + .map((webcam) => ({ + ...webcam, + ...RESORT_DOMAIN[key].webcams.find((webcamConstant) => webcamConstant.id === webcam.number), + })) as Webcam[]; + const [cameraPositions, setCameraPositions] = useState<{ - [key: string]: Position; + [key: number]: Position; }>({}); const { ref, style, api, containerRef } = useMapPinch(); - const updateCameraPosition = useCallback((id: string, position: Position) => { + const updateCameraPosition = useCallback((id: number, position: Position) => { setCameraPositions((prev) => ({ ...prev, [id]: position })); }, []); - const handleFocusSlopCamClick = ({ id, scale }: { id: string; scale: number }) => { + const handleFocusSlopCamClick = ({ id, scale }: { id: number; scale: number }) => { gtag('event', 'details_webcam_webcam_click', { detail_type: resortId, webcam_type: id }); const { width, height } = containerRef.current!.getBoundingClientRect(); const { boundedX, boundedY } = calculateWebcamPosition({ @@ -36,7 +55,7 @@ const WebCamMobileMapPage = ({ resortId }: { resortId?: number }) => { api.start({ scale: scale, x: boundedX, y: boundedY }); }; - if (!data) return; + if (!slopes || !webcams) return; return (
@@ -45,17 +64,13 @@ const WebCamMobileMapPage = ({ resortId }: { resortId?: number }) => { style={style} isWebview containerRef={containerRef} - slopes={data.slopes} - webcams={data.webcams} - MapComponent={data.MapComponent} + slopes={slopes} + webcams={webcams} + MapComponent={RESORT_DOMAIN[key].MapComponent} onCameraClick={handleFocusSlopCamClick} updateCameraPosition={updateCameraPosition} /> - +
); }; diff --git a/src/widgets/webcam/ui/webcam-map.tsx b/src/widgets/webcam/ui/webcam-map.tsx index 57cf0c6..405842f 100644 --- a/src/widgets/webcam/ui/webcam-map.tsx +++ b/src/widgets/webcam/ui/webcam-map.tsx @@ -1,21 +1,25 @@ import type { SpringValue } from '@react-spring/web'; +import type { ComponentType } from 'react'; import React, { forwardRef } from 'react'; import useSlopeStore from '@/features/slope/hooks/useSlopeStore'; import SlopeCamera from '@/features/slope/ui/slope-camera'; import SlopeMap from '@/features/slope/ui/slope-map'; -import type { Position, ResortConstant } from '@/entities/slope/model'; +import type { Position, Slope, Webcam } from '@/entities/slope/model'; import { cn } from '@/shared/lib'; -interface WebcamMapProps extends ResortConstant { +interface WebcamMapProps { isWebview?: boolean; + MapComponent: ComponentType; + slopes: Slope[]; + webcams: Webcam[]; containerRef: React.RefObject; - onCameraClick: ({ scale, id }: { scale: number; id: string }) => void; + onCameraClick: ({ scale, id }: { scale: number; id: number }) => void; style: { scale: SpringValue; x: SpringValue; y: SpringValue; }; - updateCameraPosition: (id: string, position: Position) => void; + updateCameraPosition: (id: number, position: Position) => void; } const WebcamMap = forwardRef( @@ -38,7 +42,7 @@ const WebcamMap = forwardRef(
{webcams.map((webcam) => { - const slop = slopes.filter((slop) => slop.webcamId === webcam.id); + const slop = slopes.filter((slop) => slop.webcamNo === webcam.number); // webcam을 띄워야 하는 slop를 찾음 return ( diff --git a/src/widgets/webcam/ui/webcam-slope-list.tsx b/src/widgets/webcam/ui/webcam-slope-list.tsx index bf4db30..1bb0b9f 100644 --- a/src/widgets/webcam/ui/webcam-slope-list.tsx +++ b/src/widgets/webcam/ui/webcam-slope-list.tsx @@ -2,45 +2,48 @@ import React from 'react'; import useSlopeStore from '@/features/slope/hooks/useSlopeStore'; -import type { SlopeConstant, WebcamConstant } from '@/entities/slope/model'; +import type { Slope, Webcam } from '@/entities/slope/model'; import LevelChip from '@/entities/slope/ui/level-chip'; import { cn } from '@/shared/lib'; import CameraButton from '@/shared/ui/cam-button'; interface WebcamSlopeListProps { className?: string; - list: SlopeConstant[]; - webcams: WebcamConstant[]; - onItemClick: ({ scale, id }: { scale: number; id: string }) => void; + slopes: Slope[]; + webcams: Webcam[]; + onItemClick: ({ scale, id }: { scale: number; id: number }) => void; } -const WebcamSlopeList = ({ className, list, webcams, onItemClick }: WebcamSlopeListProps) => { +const WebcamSlopeList = ({ className, slopes, webcams, onItemClick }: WebcamSlopeListProps) => { const { selectedSlope, setSelectedSlope, setSelectedCamera, setCloseCamera } = useSlopeStore(); return (
    - {list.map((item) => { + {slopes.map((item) => { + const isOpen = [item.isDayOperating, item.isNightOperating, item.isLateNightOperating].some( + (time) => time + ); return (
  • { - if (!item.isOpen) return; + if (!isOpen) return; if (selectedSlope === item.id) { setSelectedSlope(null); setSelectedCamera(null); } else { setSelectedSlope(item.id); - setSelectedCamera(item.webcamId); + setSelectedCamera(item.webcamNo); } setCloseCamera(); - if (item.webcamId) { - const webcam = webcams.find((webcam) => webcam.id === item.webcamId); + if (item.webcamNo) { + const webcam = webcams.find((webcam) => webcam.id === item.webcamNo); if (!webcam) return; onItemClick({ scale: webcam.scale, @@ -50,10 +53,10 @@ const WebcamSlopeList = ({ className, list, webcams, onItemClick }: WebcamSlopeL }} >
    -

    {item.name}

    - {item.webcamId && } +

    {item.name}

    + {item.webcamNo && }
    - +
  • ); })}