feat: 바텀시트 '관심있어요' 버튼 분리 — interested 상태 DB 저장 + 어드민 표시

- "관심있어요!" 클릭 → status='interested' (기존: dismissed와 동일했음)
- "다음에요" / 드래그 닫기 → status='dismissed'
- dismiss API에 action 파라미터 추가
- AI CRM 대시보드: interested 배지(주황) + 통계 카드 반영

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
thug0bin 2026-02-26 20:47:20 +09:00
parent 3e3934e2e5
commit a2829436d1
3 changed files with 25 additions and 10 deletions

View File

@ -2012,15 +2012,21 @@ def api_get_recommendation(user_id):
@app.route('/api/recommendation/<int:rec_id>/dismiss', methods=['POST'])
def api_dismiss_recommendation(rec_id):
"""추천 닫기"""
"""추천 닫기 / 관심 표시"""
data = request.get_json(silent=True) or {}
action = data.get('action', 'dismissed')
if action not in ('dismissed', 'interested'):
action = 'dismissed'
conn = db_manager.get_sqlite_connection()
cursor = conn.cursor()
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
cursor.execute("""
UPDATE ai_recommendations SET status = 'dismissed', dismissed_at = ?
UPDATE ai_recommendations SET status = ?, dismissed_at = ?
WHERE id = ?
""", (now, rec_id))
""", (action, now, rec_id))
conn.commit()
logging.info(f"[AI추천] id={rec_id}{action}")
return jsonify({'success': True})
@ -2100,6 +2106,7 @@ def admin_ai_crm():
SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'active' AND (expires_at IS NULL OR expires_at > datetime('now')) THEN 1 ELSE 0 END) as active_count,
SUM(CASE WHEN status = 'interested' THEN 1 ELSE 0 END) as interested_count,
SUM(CASE WHEN status = 'dismissed' THEN 1 ELSE 0 END) as dismissed_count,
SUM(CASE WHEN displayed_count > 0 THEN 1 ELSE 0 END) as displayed_count
FROM ai_recommendations

View File

@ -147,6 +147,7 @@
letter-spacing: -0.2px;
}
.badge-active { background: #dcfce7; color: #16a34a; }
.badge-interested { background: #fef3c7; color: #d97706; }
.badge-dismissed { background: #f1f5f9; color: #64748b; }
.badge-expired { background: #fee2e2; color: #dc2626; }
.badge-trigger {
@ -275,8 +276,8 @@
<div class="stat-value green">{{ stats.active_count or 0 }}</div>
</div>
<div class="stat-card">
<div class="stat-label">고객 반응 (닫기)</div>
<div class="stat-value orange">{{ stats.dismissed_count or 0 }}</div>
<div class="stat-label">관심있어요</div>
<div class="stat-value orange">{{ stats.interested_count or 0 }}</div>
</div>
<div class="stat-card">
<div class="stat-label">오늘 생성</div>
@ -332,7 +333,9 @@
<div class="msg-ellipsis" title="{{ rec.recommendation_message }}">{{ rec.recommendation_message }}</div>
</td>
<td>
{% if rec.status == 'active' and (not rec.expires_at or rec.expires_at > now) %}
{% if rec.status == 'interested' %}
<span class="badge badge-interested">관심있어요</span>
{% elif rec.status == 'active' and (not rec.expires_at or rec.expires_at > now) %}
<span class="badge badge-active">Active</span>
{% elif rec.status == 'dismissed' %}
<span class="badge badge-dismissed">Dismissed</span>

View File

@ -408,8 +408,8 @@
<div id="rec-product" style="display:inline-block;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:14px;font-weight:600;padding:8px 20px;border-radius:20px;letter-spacing:-0.2px;"></div>
</div>
<div style="display:flex;gap:12px;padding-bottom:env(safe-area-inset-bottom,0);">
<button onclick="dismissRec()" style="flex:1;padding:14px;border:1px solid #dee2e6;border-radius:14px;background:#fff;color:#868e96;font-size:15px;font-weight:600;cursor:pointer;font-family:inherit;">다음에요</button>
<button onclick="dismissRec()" style="flex:2;padding:14px;border:none;border-radius:14px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:15px;font-weight:600;cursor:pointer;font-family:inherit;">관심있어요!</button>
<button onclick="dismissRec('dismissed')" style="flex:1;padding:14px;border:1px solid #dee2e6;border-radius:14px;background:#fff;color:#868e96;font-size:15px;font-weight:600;cursor:pointer;font-family:inherit;">다음에요</button>
<button onclick="dismissRec('interested')" style="flex:2;padding:14px;border:none;border-radius:14px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:15px;font-weight:600;cursor:pointer;font-family:inherit;">관심있어요!</button>
</div>
</div>
</div>
@ -522,7 +522,8 @@
{% endif %}
});
function dismissRec() {
function dismissRec(action) {
action = action || 'dismissed';
const c = document.getElementById('rec-content');
const b = document.getElementById('rec-backdrop');
c.style.transition = 'transform .3s ease';
@ -534,7 +535,11 @@
c.style.transition = '';
c.style.transform = '';
}, 300);
if (_recId) fetch('/api/recommendation/' + _recId + '/dismiss', {method:'POST'}).catch(function(){});
if (_recId) fetch('/api/recommendation/' + _recId + '/dismiss', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({action: action})
}).catch(function(){});
}
</script>
<script>if('serviceWorker' in navigator){navigator.serviceWorker.register('/sw.js').catch(()=>{});}</script>