[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 서비스 레이어 개선
  • 개발 문서 및 가이드 개선
This commit is contained in:
2025-11-22 21:21:32 +09:00
parent ce51902150
commit ec5829eebe
10 changed files with 2514 additions and 19 deletions

View File

@@ -0,0 +1,498 @@
# 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
```javascript
themeCurationDetailInfoData: [
{
prdtId, prdtNm, // 상품 ID, 이름
imgUrls600: [], // 이미지 배열
priceInfo: "299|199|Y|...", // 가격 정보 (파이프 구분)
prdtMediaUrl, // 비디오 URL
showId, showNm, // 쇼 정보
catCd, catNm, // 카테고리
soldoutFlag, // 매진 여부
pmtSuptYn, // 결제 지원
revwGrd, // 평점
}
]
```
#### Hotel Product
```javascript
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
```javascript
// 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
```javascript
// 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.5~3.4) / Very Good (3.5~4.4) / Excellent (≥4.5)
**비디오 지원 없음**
**옵션 선택 없음** (숙박 정보는 미리 정해짐)
---
### 5. 결제 여부 판단
#### 공통점
```javascript
// 결제 OS 버전 체크
webOSVersion >= "6.0" // TRUE일 때만 결제 UI 표시
```
#### Theme Product
```javascript
const isBillingProductVisible = (
productInfo[selectedIndex]?.pmtSuptYn === "Y" &&
webOSVersion >= "6.0"
);
// YES → ShowSingleOption (구매 옵션)
// NO → ShowUnableOption (구매불가)
```
#### Hotel Product
```javascript
// 호텔은 pmtSuptYn 체크 없음 (모두 구매불가)
// SMS "SEE MORE" 버튼만 제공
// 모든 호텔 상품이 UnableOption 구조
```
---
### 6. SMS 타입 코드
#### Theme Product
```javascript
smsTpCd = "APP00204" // 테마/쇼 상품
```
#### Hotel Product
```javascript
smsTpCd = "APP00205" // 호텔 상품
```
---
### 7. 로그 필드
#### 공통 필드
```javascript
{
curationId, curationNm, // 테마/큐레이션
patnrId, patncNm, // 파트너
prdtId, prdtNm, // 상품 ID, 이름
revwGrd, // 평점
expsOrd, // 상품 순번
}
```
#### Theme Product 추가 필드
```javascript
{
showId, showNm, // 쇼 정보
catCd, catNm, // 카테고리
befPrice, lastPrice, // 원가, 할인가
rewdAplyFlag, // 보상 적용
tsvFlag, // 오늘의 특가
shopTpNm: "product", // 상품 타입
}
```
#### Hotel Product 추가 필드
```javascript
{
hotelId, // 호텔 ID (prdtId 대체)
price, // 가격 (단순)
shopTpNm: "hotel", // 상품 타입
}
```
---
### 8. 선택 인덱스 처리
#### Theme Product
```javascript
// URL 파라미터로 특정 상품 지정
if (panelInfo?.themePrdtId) {
for (let i = 0; i < themeProductInfos.length; i++) {
if (themeProductInfos[i].prdtId === panelInfo?.themePrdtId) {
setSelectedIndex(i); // ← 해당 상품으로 이동
}
}
}
```
#### Hotel Product
```javascript
// 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에 분기 추가**
```javascript
if (panelInfo?.type === "newtype") {
dispatch(getNewTypeDetailInfo(...));
}
```
2. **Redux Action/Reducer 생성**
```javascript
GET_NEWTYPE_DETAIL_INFO action 추가
state.home.newTypeData 상태 추가
```
3. **메인 컴포넌트 생성** (ShowProduct/HotelProduct 참고)
- ThemeIndicator 재사용 (또는 커스터마이징)
- IndicatorOptions 재사용 (또는 커스터마이징)
- 세부 UI 컴포넌트 작성
4. **ThemeProduct에 라우팅 추가**
```javascript
{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의 차이점을 명확히 이해할 수 있으며, 향후 유사한 상품 타입 추가 시 참고할 수 있습니다.