feat: 회원 상세 - 관심 상품 탭 추가
- AI 업셀링에서 '관심있어요' 표시한 상품 조회
- status='interested'인 ai_recommendations 조회
- 상품명, 추천 메시지, 구매 상품(트리거) 표시
- 💝 관심 탭 UI 구현
This commit is contained in:
parent
79369d9a56
commit
753df2c13c
@ -3023,6 +3023,7 @@ def api_member_history(phone):
|
||||
'mileage': None,
|
||||
'purchases': [], # 전체 구매 이력
|
||||
'prescriptions': [], # 조제 이력
|
||||
'interests': [], # 관심 상품 (AI 업셀링)
|
||||
'pos_customer': None
|
||||
}
|
||||
|
||||
@ -3083,6 +3084,28 @@ def api_member_history(phone):
|
||||
'member_since': user['created_at'],
|
||||
'transactions': tx_list
|
||||
}
|
||||
|
||||
# 관심 상품 조회 (AI 업셀링에서 '관심있어요' 표시한 것)
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
id, recommended_product, recommendation_message,
|
||||
recommendation_reason, trigger_products, created_at
|
||||
FROM ai_recommendations
|
||||
WHERE user_id = ? AND status = 'interested'
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 20
|
||||
""", (user_id,))
|
||||
interests = cursor.fetchall()
|
||||
|
||||
result['interests'] = [{
|
||||
'id': i['id'],
|
||||
'product': i['recommended_product'],
|
||||
'message': i['recommendation_message'],
|
||||
'reason': i['recommendation_reason'],
|
||||
'trigger_products': i['trigger_products'],
|
||||
'created_at': i['created_at']
|
||||
} for i in interests]
|
||||
|
||||
except Exception as e:
|
||||
logging.warning(f"마일리지 조회 실패: {e}")
|
||||
|
||||
|
||||
@ -613,6 +613,7 @@
|
||||
<div class="detail-tab active" data-tab="mileage" onclick="switchDetailTab('mileage')">📊 적립</div>
|
||||
<div class="detail-tab" data-tab="purchase" onclick="switchDetailTab('purchase')">🛒 구매</div>
|
||||
<div class="detail-tab" data-tab="prescription" onclick="switchDetailTab('prescription')">💊 조제</div>
|
||||
<div class="detail-tab" data-tab="interest" onclick="switchDetailTab('interest')">💝 관심</div>
|
||||
</div>
|
||||
<div class="detail-content" id="detailContent">
|
||||
<div class="detail-loading">데이터를 불러오는 중...</div>
|
||||
@ -893,6 +894,8 @@
|
||||
renderPurchaseTab(content);
|
||||
} else if (currentDetailTab === 'prescription') {
|
||||
renderPrescriptionTab(content);
|
||||
} else if (currentDetailTab === 'interest') {
|
||||
renderInterestTab(content);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1035,6 +1038,47 @@
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function renderInterestTab(container) {
|
||||
// AI 업셀링에서 '관심있어요' 표시한 상품
|
||||
if (!detailData.interests || detailData.interests.length === 0) {
|
||||
container.innerHTML = '<div class="detail-empty">💝 관심 상품이 없습니다<br><small style="color:#94a3b8;">마일리지 적립 시 AI 추천에서 "관심있어요"를 누르면<br>여기에 표시됩니다</small></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = detailData.interests.map(item => {
|
||||
// 날짜 포맷
|
||||
const date = item.created_at ? new Date(item.created_at).toLocaleString('ko-KR', {
|
||||
month: 'short', day: 'numeric'
|
||||
}) : '';
|
||||
|
||||
// 트리거 상품 (JSON 파싱)
|
||||
let triggerText = '';
|
||||
try {
|
||||
const triggers = JSON.parse(item.trigger_products || '[]');
|
||||
if (triggers.length > 0) {
|
||||
triggerText = triggers.join(', ');
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
return `
|
||||
<div class="purchase-card" style="border-left: 3px solid #ec4899;">
|
||||
<div class="purchase-header">
|
||||
<span style="font-size:15px;font-weight:700;color:#ec4899;">💝 ${escapeHtml(item.product)}</span>
|
||||
<span class="purchase-date">${date}</span>
|
||||
</div>
|
||||
<div style="font-size:13px;color:#475569;margin:8px 0;line-height:1.5;">
|
||||
${escapeHtml(item.message || '')}
|
||||
</div>
|
||||
${triggerText ? `
|
||||
<div style="font-size:11px;color:#94a3b8;margin-top:8px;">
|
||||
🛒 구매 상품: ${escapeHtml(triggerText)}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function openSendFromDetail() {
|
||||
if (!currentDetailMember) return;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user