From a2829436d1a69370368bd96c0c6c6ea21b20bc00 Mon Sep 17 00:00:00 2001 From: thug0bin Date: Thu, 26 Feb 2026 20:47:20 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20?= =?UTF-8?q?'=EA=B4=80=EC=8B=AC=EC=9E=88=EC=96=B4=EC=9A=94'=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EB=B6=84=EB=A6=AC=20=E2=80=94=20interested=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20DB=20=EC=A0=80=EC=9E=A5=20+=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - "관심있어요!" 클릭 → status='interested' (기존: dismissed와 동일했음) - "다음에요" / 드래그 닫기 → status='dismissed' - dismiss API에 action 파라미터 추가 - AI CRM 대시보드: interested 배지(주황) + 통계 카드 반영 Co-Authored-By: Claude Opus 4.6 --- backend/app.py | 13 ++++++++++--- backend/templates/admin_ai_crm.html | 9 ++++++--- backend/templates/my_page.html | 13 +++++++++---- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/backend/app.py b/backend/app.py index 4ba8651..ed822ae 100644 --- a/backend/app.py +++ b/backend/app.py @@ -2012,15 +2012,21 @@ def api_get_recommendation(user_id): @app.route('/api/recommendation//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 diff --git a/backend/templates/admin_ai_crm.html b/backend/templates/admin_ai_crm.html index 9c47654..2f3398b 100644 --- a/backend/templates/admin_ai_crm.html +++ b/backend/templates/admin_ai_crm.html @@ -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 @@
{{ stats.active_count or 0 }}
-
고객 반응 (닫기)
-
{{ stats.dismissed_count or 0 }}
+
관심있어요
+
{{ stats.interested_count or 0 }}
오늘 생성
@@ -332,7 +333,9 @@
{{ rec.recommendation_message }}
- {% if rec.status == 'active' and (not rec.expires_at or rec.expires_at > now) %} + {% if rec.status == 'interested' %} + 관심있어요 + {% elif rec.status == 'active' and (not rec.expires_at or rec.expires_at > now) %} Active {% elif rec.status == 'dismissed' %} Dismissed diff --git a/backend/templates/my_page.html b/backend/templates/my_page.html index d155367..48ebee6 100644 --- a/backend/templates/my_page.html +++ b/backend/templates/my_page.html @@ -408,8 +408,8 @@
- - + +
@@ -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(){}); }