Files
shoptime/com.twin.app.shoptime/THEME_VS_HOTEL_COMPARISON.md
optrader ec5829eebe [251122] fix: DetailPanel Theme,Hotels - 1
🕐 커밋 시간: 2025. 11. 22. 21:21:31

📊 변경 통계:
  • 총 파일: 10개
  • 추가: +76줄
  • 삭제: -19줄

📁 추가된 파일:
  + com.twin.app.shoptime/HOTEL_UI_HANDLING_REPORT.md
  + com.twin.app.shoptime/HOTEL_UI_VISUAL_GUIDE.md
  + com.twin.app.shoptime/THEME_PRODUCT_UI_ANALYSIS.md
  + com.twin.app.shoptime/THEME_PRODUCT_VISUAL_GUIDE.md
  + com.twin.app.shoptime/THEME_VS_HOTEL_COMPARISON.md
  + com.twin.app.shoptime/docs/todo/251122-detailpanel-diff.md

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/api/TAxios.js
  ~ com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.module.less

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx (javascript):
     Added: extractProductMeta()
    🔄 Modified: SpotlightContainerDecorator()
     Deleted: SpotlightContainerDecorator()
  📄 com.twin.app.shoptime/HOTEL_UI_HANDLING_REPORT.md (md파일):
     Added: useEffect(), dispatch(), ThemeProduct(), setLabel(), Map(), forEach(), filter(), findIndex(), setAmenitiesInfos(), setSelectedIndex()
  📄 com.twin.app.shoptime/HOTEL_UI_VISUAL_GUIDE.md (md파일):
     Added: DetailPanel(), getThemeCurationDetailInfo(), getThemeHotelDetailInfo(), getMainCategoryDetail(), THeader(), TBody(), ThemeProduct(), Container(), rating(), TButton(), YouMayLike(), MobileSendPopUp(), selectedIndex(), setSelectedIndex(), ellipsis(), amenitiesBox(), c70850(), handleSMSClick(), dispatch(), clearThemeDetail()
  📄 com.twin.app.shoptime/THEME_PRODUCT_UI_ANALYSIS.md (md파일):
     Added: getThemeCurationDetailInfo(), productData(), Container(), ShowSingleOption(), ShowUnableOption(), useState(), useEffect(), setSelectedImage(), useMemo(), dispatch(), startVideoPlayer(), productDescription(), setTimeout(), useCallback(), isProductSoldOut(), ProductOption(), setSelectedIndex()
  📄 com.twin.app.shoptime/THEME_PRODUCT_VISUAL_GUIDE.md (md파일):
     Added: ShowProduct(), Container(), optionContainer(), ShowSingleOption(), ProductOption(), ShowUnableOption(), UnableOption(), selectedIndex(), setSelectedIndex(), descriptionClick(), setTabLabel(), setDescription(), dispatch(), handleIndicatorOptions(), handleSMSClick(), handleMobileSendPopupOpen(), setImageSelectedIndex(), StarRating(), ProductTag(), SingleOption()
  📄 com.twin.app.shoptime/THEME_VS_HOTEL_COMPARISON.md (md파일):
     Added: Product(), UnableOption(), StarRating(), dispatch(), getThemeCurationDetailInfo(), getThemeHotelDetailInfo()

🔧 주요 변경 내용:
  • API 서비스 레이어 개선
  • 개발 문서 및 가이드 개선
2025-11-22 21:21:32 +09:00

12 KiB
Raw Permalink Blame History

DetailPanel - Theme Product vs Hotel Product 비교 분석

📊 전체 개요

구분 Theme Product (쇼/공연) Hotel Product (숙박)
데이터 소스 themeCurationDetailInfoData[] themeCurationHotelDetailData[]
메인 컴포넌트 ShowProduct HotelProduct
패널 타입 panelInfo.type === "theme" panelInfo.type === "hotel"
서버 API getThemeCurationDetailInfo getThemeHotelDetailInfo
Redux 액션 GET_THEME_CURATION_DETAIL_INFO GET_THEME_HOTEL_DETAIL_INFO

🎯 핵심 차이점

1. 데이터 구조

Theme Product

themeCurationDetailInfoData: [
  {
    prdtId, prdtNm,           // 상품 ID, 이름
    imgUrls600: [],           // 이미지 배열
    priceInfo: "299|199|Y|...", // 가격 정보 (파이프 구분)
    prdtMediaUrl,             // 비디오 URL
    showId, showNm,           // 쇼 정보
    catCd, catNm,             // 카테고리
    soldoutFlag,              // 매진 여부
    pmtSuptYn,                // 결제 지원
    revwGrd,                  // 평점
  }
]

Hotel Product

themeCurationHotelDetailData: [
  {
    hotelId, hotelNm,         // 호텔 ID, 이름
    hotelImgUrl,              // 호텔 썸네일
    imgUrls600: [],           // 이미지 배열
    qrcodeUrl,                // QR 코드
    hotelDetailInfo: {
      price,                  // 가격 (단순 숫자)
      currencySign,           // 통화 기호
      revwGrd,                // 평점
      hotelType,              // 호텔 타입
      hotelAddr,              // 주소
      nights, adultsCount,    // 숙박일, 성인 수
      roomType,               // 방 타입
      amenities: [],          // 편의시설 ID 배열
      imgUrls: []             // 이미지
    }
  }
]

hotelData: {
  hotelInfo: { curationId, curationNm, ... },
  amenities: [
    { amntId, lgAmntNm, lgAmntImgUrl },
    // ...
  ]
}

2. UI 구조

Theme Product

ShowProduct
├─ ThemeIndicator
│  ├─ [메인 이미지] 또는 [비디오]
│  └─ [썸네일 스크롤]
├─ IndicatorOptions
│  ├─ [설명] [교환정책] [SMS]
│  └─ QR 코드
└─ ShowSingleOption / ShowUnableOption
   └─ 구매 옵션 또는 구매불가 메시지

Hotel Product

HotelProduct
├─ ThemeIndicator
│  ├─ [메인 이미지]
│  └─ [썸네일 스크롤]
├─ IndicatorOptions
│  └─ [주소 정보]
└─ optionContainer
   ├─ [로고 + 별점]
   ├─ [호텔명 + 타입]
   ├─ [편의시설 그리드] (최대 10개)
   ├─ [예약정보 + 가격 + QR]
   └─ [SEE MORE] 버튼

3. 가격 처리

Theme Product

// priceInfo = "299|199|Y|discount10|10%"
const befPrice = priceInfo.split("|")[0];      // 원가
const lastPrice = priceInfo.split("|")[1];     // 할인가
const rewdAplyFlag = priceInfo.split("|")[2];  // 보상 적용
const discountRate = priceInfo.split("|")[4];  // 할인율

// 로그 전송
params.befPrice = befPrice;
params.lastPrice = lastPrice;

Hotel Product

// price = "299.99" (단순 숫자)
// currencySign = "$"

// UI 표시
<div>
  {hotelInfos[selectedIndex]?.hotelDetailInfo.currencySign}
  {hotelInfos[selectedIndex]?.hotelDetailInfo.price}
</div>

// 로그 전송
params.price = selectedHotelInfo.hotelInfo?.hotelDetailInfo?.price;

4. 특수 기능

Theme Product

비디오 자동 재생

  • prdtMediaUrl 존재 시 첫 이미지 위치에 비디오
  • launchedFromPlayer = false일 때만 자동 재생
  • 비디오 자막 지원 (prdtMediaSubtitlUrl)

상세 정보 팝업

  • [DESCRIPTION] 버튼: 상품 설명
  • [RETURNS & EXCHANGES] 버튼: 반품/교환 정책
  • HTML 마크업 지원 (dangerouslySetInnerHTML)

결제 옵션 선택

  • 옵션 선택 (이용일자, 좌석 등)
  • 수량 선택
  • 옵션별 가격 계산

편의시설 표시 없음


Hotel Product

편의시설 그리드 표시

  • 최대 10개 편의시설 아이콘 + 텍스트
  • 같은 카테고리 중복 제거
  • 편의시설별 이미지 및 설명

예약 정보 표시

  • 숙박 기간 (nights)
  • 성인 수 (adultsCount)
  • 방 타입 (roomType)
  • 자동 포맷팅 (예: "2 Nights 2 Adults")

별점 등급 시스템

  • 평점 수치 → 문자 등급 변환
  • Fair (≤2.4) / Good (2.53.4) / Very Good (3.54.4) / Excellent (≥4.5)

비디오 지원 없음 옵션 선택 없음 (숙박 정보는 미리 정해짐)


5. 결제 여부 판단

공통점

// 결제 OS 버전 체크
webOSVersion >= "6.0" // TRUE일 때만 결제 UI 표시

Theme Product

const isBillingProductVisible = (
  productInfo[selectedIndex]?.pmtSuptYn === "Y" &&
  webOSVersion >= "6.0"
);

// YES → ShowSingleOption (구매 옵션)
// NO → ShowUnableOption (구매불가)

Hotel Product

// 호텔은 pmtSuptYn 체크 없음 (모두 구매불가)
// SMS "SEE MORE" 버튼만 제공

// 모든 호텔 상품이 UnableOption 구조

6. SMS 타입 코드

Theme Product

smsTpCd = "APP00204"  // 테마/쇼 상품

Hotel Product

smsTpCd = "APP00205"  // 호텔 상품

7. 로그 필드

공통 필드

{
  curationId, curationNm,     // 테마/큐레이션
  patnrId, patncNm,           // 파트너
  prdtId, prdtNm,             // 상품 ID, 이름
  revwGrd,                    // 평점
  expsOrd,                    // 상품 순번
}

Theme Product 추가 필드

{
  showId, showNm,             // 쇼 정보
  catCd, catNm,               // 카테고리
  befPrice, lastPrice,        // 원가, 할인가
  rewdAplyFlag,               // 보상 적용
  tsvFlag,                    // 오늘의 특가
  shopTpNm: "product",        // 상품 타입
}

Hotel Product 추가 필드

{
  hotelId,                    // 호텔 ID (prdtId 대체)
  price,                      // 가격 (단순)
  shopTpNm: "hotel",          // 상품 타입
}

8. 선택 인덱스 처리

Theme Product

// URL 파라미터로 특정 상품 지정
if (panelInfo?.themePrdtId) {
  for (let i = 0; i < themeProductInfos.length; i++) {
    if (themeProductInfos[i].prdtId === panelInfo?.themePrdtId) {
      setSelectedIndex(i);  // ← 해당 상품으로 이동
    }
  }
}

Hotel Product

// URL 파라미터로 특정 호텔 지정
if (panelInfo?.themeHotelId) {
  for (let i = 0; i < hotelInfos.length; i++) {
    if (hotelInfos[i].hotelId === panelInfo?.themeHotelId) {
      setSelectedIndex(i);  // ← 해당 호텔로 이동
    }
  }
}

📐 레이아웃 비교

Theme Product

요소 크기
ThemeIndicator 834×930px
메인 이미지 600×600px
썸네일 150×150px (반복)
QR 코드 160×160px

Hotel Product

요소 크기
ThemeIndicator 774×930px
메인 이미지 600×600px
optionContainer 1026×990px
편의시설 박스 138×138px (반복, 최대 10개)
QR 코드 160×160px

🔄 컴포넌트 재사용

공유 컴포넌트

ThemeIndicator
├─ Theme Product에서 사용
└─ Hotel Product에서도 사용
   (비디오 재생은 X)

IndicatorOptions
├─ Theme Product에서 사용
└─ Hotel Product에서도 사용
   (주소 정보만 표시)

StarRating
├─ Theme Product에서 사용
└─ Hotel Product에서도 사용

전용 컴포넌트

Theme Product:
├─ ShowProduct.jsx
├─ ShowSingleOption.jsx
├─ ShowUnableOption.jsx
└─ SingleOption / UnableOption (기존)

Hotel Product:
├─ HotelProduct.jsx
└─ StarRating (호텔 등급용)

📊 정리 테이블

기능 Theme Hotel
비디오 지원
자동 재생
편의시설 표시 (최대 10개)
예약 정보 (숙박일, 성인 수)
등급 변환 (Fair/Good/Very Good/Excellent)
옵션 선택
수량 선택
결제 가능 조건부 (pmtSuptYn) (항상 불가)
상세 팝업 (설명/교환)
가격 형식 "299|199|Y|..." "299.99"
통화 기호 미사용 ($, , ¥ 등)
SMS 타입 APP00204 APP00205
QR 코드
로그 추적 상세 (가격, 할인율) 기본 (가격만)

🎯 사용 시나리오

Theme Product 사용 예

사용자가 "오페라 공연" 클릭
  ↓
DetailPanel 로드 (type: "theme")
  ↓
ShowProduct 렌더링
  ↓
공연 비디오 자동 재생
  ↓
사용자가 설명 버튼 클릭
  ↓
상품 설명 팝업 표시
  ↓
사용자가 SMS 버튼 클릭
  ↓
친구에게 공연 정보 전송

Hotel Product 사용 예

사용자가 "두바이 호텔" 클릭
  ↓
DetailPanel 로드 (type: "hotel")
  ↓
HotelProduct 렌더링
  ↓
호텔 사진, 편의시설, 가격 표시
  ↓
사용자가 화살표로 다른 호텔 선택
  ↓
별점/편의시설/가격 업데이트
  ↓
사용자가 SEE MORE 버튼 클릭
  ↓
호텔 상세 정보 SMS 전송

💡 개발 가이드

새로운 상품 타입 추가 시

  1. DetailPanel에 분기 추가

    if (panelInfo?.type === "newtype") {
      dispatch(getNewTypeDetailInfo(...));
    }
    
  2. Redux Action/Reducer 생성

    GET_NEWTYPE_DETAIL_INFO action 추가
    state.home.newTypeData 상태 추가
    
  3. 메인 컴포넌트 생성 (ShowProduct/HotelProduct 참고)

    • ThemeIndicator 재사용 (또는 커스터마이징)
    • IndicatorOptions 재사용 (또는 커스터마이징)
    • 세부 UI 컴포넌트 작성
  4. ThemeProduct에 라우팅 추가

    {themeType === "newtype" && (
      <NewTypeProduct {...props} />
    )}
    

🔗 관련 파일 구조

src/views/DetailPanel/
├─ DetailPanel.jsx / DetailPanel.backup.jsx
├─ ThemeProduct/
│  ├─ ThemeProduct.jsx (라우팅)
│  ├─ ShowProduct.jsx (테마 상품)
│  ├─ HotelProduct.jsx (호텔 상품)
│  ├─ ShowOptions/
│  │  ├─ ShowSingleOption.jsx
│  │  └─ ShowUnableOption.jsx
│  └─ *.module.less
├─ components/
│  ├─ ProductOption.jsx (래퍼)
│  ├─ indicator/
│  │  ├─ ThemeIndicator.jsx (공유)
│  │  ├─ IndicatorOptions.jsx (공유)
│  │  └─ *.module.less
│  ├─ StarRating.jsx (공유)
│  └─ ...
├─ SingleProduct/
│  └─ SingleOption.jsx (테마용)
├─ UnableProduct/
│  └─ UnableOption.jsx (테마용)
└─ ...

src/actions/
├─ homeActions.js
│  ├─ getThemeCurationDetailInfo()
│  └─ getThemeHotelDetailInfo()
└─ ...

src/reducers/
└─ homeReducer.js
   ├─ GET_THEME_CURATION_DETAIL_INFO case
   └─ GET_THEME_HOTEL_DETAIL_INFO case

최종 체크리스트

Theme Product

  • 비디오 자동 재생 (조건부)
  • 상세 정보 팝업 (설명/교환)
  • 옵션 선택 (날짜/좌석)
  • 수량 선택
  • 가격 할인율 표시
  • 결제 가능 여부 판단
  • SMS 공유 (모든 상품)
  • 상세 로깅

Hotel Product

  • 호텔 이미지 갤러리
  • 편의시설 그리드 (최대 10개)
  • 별점 등급 변환
  • 예약 정보 표시 (숙박일, 성인 수)
  • 가격 + 통화 기호
  • 주소 정보
  • QR 코드
  • SMS 공유 (SEE MORE)
  • 로깅

이 문서를 통해 Theme Product와 Hotel Product의 차이점을 명확히 이해할 수 있으며, 향후 유사한 상품 타입 추가 시 참고할 수 있습니다.