feat: 관리자 대시보드 사용자 모달에 반려동물 탭 추가
- /admin/user/<id> API에 pets 데이터 추가
- 사용자 상세 모달에 🐾 반려동물 탭 추가
- 반려동물 사진, 이름, 종류, 품종, 성별, 등록일 표시
This commit is contained in:
parent
1cebb02ec6
commit
52a4f69abc
@ -1621,7 +1621,38 @@ def admin_user_detail(user_id):
|
|||||||
except Exception as interest_error:
|
except Exception as interest_error:
|
||||||
logging.warning(f"관심상품 조회 실패 (user {user_id}): {interest_error}")
|
logging.warning(f"관심상품 조회 실패 (user {user_id}): {interest_error}")
|
||||||
|
|
||||||
# 8. 응답 생성
|
# 8. 반려동물 조회
|
||||||
|
pets = []
|
||||||
|
try:
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT id, name, species, breed, gender, birth_date, age_months,
|
||||||
|
weight, photo_url, notes, created_at
|
||||||
|
FROM pets
|
||||||
|
WHERE user_id = ? AND is_active = TRUE
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
""", (user_id,))
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
species_label = '강아지 🐕' if row['species'] == 'dog' else ('고양이 🐈' if row['species'] == 'cat' else '기타')
|
||||||
|
gender_label = '♂ 남아' if row['gender'] == 'male' else ('♀ 여아' if row['gender'] == 'female' else '')
|
||||||
|
pets.append({
|
||||||
|
'id': row['id'],
|
||||||
|
'name': row['name'],
|
||||||
|
'species': row['species'],
|
||||||
|
'species_label': species_label,
|
||||||
|
'breed': row['breed'],
|
||||||
|
'gender': row['gender'],
|
||||||
|
'gender_label': gender_label,
|
||||||
|
'birth_date': row['birth_date'],
|
||||||
|
'age_months': row['age_months'],
|
||||||
|
'weight': float(row['weight']) if row['weight'] else None,
|
||||||
|
'photo_url': row['photo_url'],
|
||||||
|
'notes': row['notes'],
|
||||||
|
'created_at': utc_to_kst_str(row['created_at'])
|
||||||
|
})
|
||||||
|
except Exception as pet_error:
|
||||||
|
logging.warning(f"반려동물 조회 실패 (user {user_id}): {pet_error}")
|
||||||
|
|
||||||
|
# 9. 응답 생성
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': True,
|
'success': True,
|
||||||
'user': {
|
'user': {
|
||||||
@ -1647,7 +1678,8 @@ def admin_user_detail(user_id):
|
|||||||
'purchases': purchases,
|
'purchases': purchases,
|
||||||
'prescriptions': prescriptions,
|
'prescriptions': prescriptions,
|
||||||
'pos_customer': pos_customer,
|
'pos_customer': pos_customer,
|
||||||
'interests': interests
|
'interests': interests,
|
||||||
|
'pets': pets
|
||||||
})
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
BIN
backend/static/uploads/pets/pet_2_9919f990.jpg
Normal file
BIN
backend/static/uploads/pets/pet_2_9919f990.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
BIN
backend/static/uploads/pets/pet_3_53b73509.png
Normal file
BIN
backend/static/uploads/pets/pet_3_53b73509.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 MiB |
@ -913,6 +913,9 @@
|
|||||||
<button onclick="switchTab('interests')" id="tab-interests" class="tab-btn" style="padding: 12px 20px; border: none; background: none; font-size: 15px; font-weight: 600; cursor: pointer; border-bottom: 3px solid transparent; color: #868e96;">
|
<button onclick="switchTab('interests')" id="tab-interests" class="tab-btn" style="padding: 12px 20px; border: none; background: none; font-size: 15px; font-weight: 600; cursor: pointer; border-bottom: 3px solid transparent; color: #868e96;">
|
||||||
💝 관심 (${data.interests ? data.interests.length : 0})
|
💝 관심 (${data.interests ? data.interests.length : 0})
|
||||||
</button>
|
</button>
|
||||||
|
<button onclick="switchTab('pets')" id="tab-pets" class="tab-btn" style="padding: 12px 20px; border: none; background: none; font-size: 15px; font-weight: 600; cursor: pointer; border-bottom: 3px solid transparent; color: #868e96;">
|
||||||
|
🐾 반려동물 (${data.pets ? data.pets.length : 0})
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 정렬 버튼 (구매 이력용) -->
|
<!-- 정렬 버튼 (구매 이력용) -->
|
||||||
@ -1070,6 +1073,53 @@
|
|||||||
html += '<p style="text-align: center; padding: 40px; color: #868e96;">💝 관심 상품이 없습니다<br><small>마일리지 적립 시 AI 추천에서 "관심있어요"를 누르면 여기에 표시됩니다</small></p>';
|
html += '<p style="text-align: center; padding: 40px; color: #868e96;">💝 관심 상품이 없습니다<br><small>마일리지 적립 시 AI 추천에서 "관심있어요"를 누르면 여기에 표시됩니다</small></p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html += `
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 반려동물 탭 -->
|
||||||
|
<div id="tab-content-pets" class="tab-content" style="display: none;">
|
||||||
|
`;
|
||||||
|
|
||||||
|
// 반려동물 렌더링
|
||||||
|
const pets = data.pets || [];
|
||||||
|
if (pets.length > 0) {
|
||||||
|
html += '<div style="display: grid; gap: 16px;">';
|
||||||
|
pets.forEach(pet => {
|
||||||
|
const photoHtml = pet.photo_url
|
||||||
|
? `<img src="${pet.photo_url}" alt="${pet.name}" style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover;">`
|
||||||
|
: `<div style="width: 80px; height: 80px; border-radius: 50%; background: linear-gradient(135deg, #fbbf24, #f59e0b); display: flex; align-items: center; justify-content: center; font-size: 36px;">${pet.species === 'dog' ? '🐕' : (pet.species === 'cat' ? '🐈' : '🐾')}</div>`;
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<div style="border: 1px solid #e9ecef; border-radius: 16px; padding: 20px; display: flex; gap: 20px; align-items: center; border-left: 4px solid #f59e0b;">
|
||||||
|
<div style="flex-shrink: 0;">
|
||||||
|
${photoHtml}
|
||||||
|
</div>
|
||||||
|
<div style="flex: 1;">
|
||||||
|
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 8px;">
|
||||||
|
<span style="font-size: 20px; font-weight: 700; color: #212529;">${pet.name}</span>
|
||||||
|
<span style="background: ${pet.species === 'dog' ? '#dbeafe' : '#fce7f3'}; color: ${pet.species === 'dog' ? '#1e40af' : '#9d174d'}; font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 20px;">
|
||||||
|
${pet.species_label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-wrap: wrap; gap: 12px; font-size: 14px; color: #6b7280;">
|
||||||
|
${pet.breed ? `<span>🏷️ ${pet.breed}</span>` : ''}
|
||||||
|
${pet.gender_label ? `<span>${pet.gender_label}</span>` : ''}
|
||||||
|
${pet.weight ? `<span>⚖️ ${pet.weight}kg</span>` : ''}
|
||||||
|
${pet.age_months ? `<span>🎂 ${pet.age_months}개월</span>` : ''}
|
||||||
|
</div>
|
||||||
|
${pet.notes ? `<div style="margin-top: 8px; font-size: 13px; color: #9ca3af; background: #f9fafb; padding: 8px 12px; border-radius: 8px;">📝 ${pet.notes}</div>` : ''}
|
||||||
|
<div style="margin-top: 10px; font-size: 12px; color: #d1d5db;">
|
||||||
|
등록일: ${pet.created_at}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
html += '</div>';
|
||||||
|
} else {
|
||||||
|
html += '<p style="text-align: center; padding: 40px; color: #868e96;">🐾 등록된 반려동물이 없습니다<br><small>고객이 마이페이지에서 반려동물을 등록하면 여기에 표시됩니다</small></p>';
|
||||||
|
}
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -1727,6 +1777,13 @@
|
|||||||
// KIMS 약물 상호작용 체크
|
// KIMS 약물 상호작용 체크
|
||||||
// ═══════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════
|
||||||
|
|
||||||
|
function escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
async function checkDrugInteraction(drugCodes, preSerial) {
|
async function checkDrugInteraction(drugCodes, preSerial) {
|
||||||
// drugCodes가 문자열로 넘어올 수 있음
|
// drugCodes가 문자열로 넘어올 수 있음
|
||||||
if (typeof drugCodes === 'string') {
|
if (typeof drugCodes === 'string') {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user