Spaces:
Sleeping
Sleeping
| """Trigger analysis section β date picker, run, preview, save. | |
| Separated from overview.py so that CRUD operations work even when | |
| trigger_rules module is unavailable (e.g., standalone HuggingFace Space). | |
| """ | |
| from datetime import date, timedelta | |
| import streamlit as st | |
| from core.supabase_client import ( | |
| get_campaign_date_range, | |
| save_action_items_batch, | |
| ) | |
| from .triggers import TRIGGERS_AVAILABLE | |
| from .utils import priority_level, CATEGORY_CONFIG | |
| def render_analysis_section(campaign_id: int, base_ctx: dict): | |
| """Render trigger analysis: date picker, run button, preview, save.""" | |
| with st.expander("π νΈλ¦¬κ±° λΆμ μ€ν", expanded=True): | |
| if not TRIGGERS_AVAILABLE: | |
| st.info( | |
| "νΈλ¦¬κ±° λΆμ κΈ°λ₯μ μ¬μ©ν μ μμ΅λλ€. " | |
| "μ 체 νλ‘μ νΈ νκ²½μμλ§ μ§μλ©λλ€." | |
| ) | |
| return | |
| # Date range | |
| date_range = get_campaign_date_range(campaign_id) | |
| if not date_range: | |
| st.info("μΊ νμΈ λ°μ΄ν°κ° μμ§ λκΈ°νλμ§ μμμ΅λλ€.") | |
| return | |
| _, last_date_str = date_range | |
| last_date = date.fromisoformat(last_date_str) | |
| default_start = last_date - timedelta(days=6) | |
| date_cols = st.columns(2) | |
| with date_cols[0]: | |
| start_date = st.date_input( | |
| "μμμΌ", | |
| value=default_start, | |
| key="ai_trigger_start", | |
| ) | |
| with date_cols[1]: | |
| end_date = st.date_input( | |
| "μ’ λ£μΌ", | |
| value=last_date, | |
| key="ai_trigger_end", | |
| ) | |
| if st.button("π λΆμ μ€ν", key="ai_run_triggers", type="primary", use_container_width=True): | |
| with st.spinner("14κ° νΈλ¦¬κ±° κ·μΉμ νκ° μ€..."): | |
| try: | |
| from .triggers import evaluate_triggers | |
| results = evaluate_triggers( | |
| campaign_id, | |
| start_date.isoformat(), | |
| end_date.isoformat(), | |
| ) | |
| st.session_state["ai_trigger_results"] = results | |
| except Exception as e: | |
| st.error(f"λΆμ μ€λ₯: {e}") | |
| return | |
| # Show results if available | |
| results = st.session_state.get("ai_trigger_results") | |
| if results is None: | |
| return | |
| if not results: | |
| st.success("λͺ¨λ μ§νκ° μ μ λ²μμ λλ€. νμ§λ μ νΈκ° μμ΅λλ€.") | |
| return | |
| st.markdown(f"**{len(results)}κ° μ νΈ νμ§λ¨**") | |
| # Preview cards | |
| for item in results: | |
| p_label, p_color, p_bg = priority_level(item["priority"]) | |
| cat_cfg = CATEGORY_CONFIG.get(item["category"], {"color": "#666", "icon": "π"}) | |
| st.markdown(f""" | |
| <div style="background:#FAFAFA;border:1px solid #E5E7EB;border-radius:8px; | |
| padding:12px;margin-bottom:8px;border-left:3px solid {p_color}"> | |
| <div style="display:flex;gap:8px;align-items:center;margin-bottom:6px"> | |
| <span style="background:{p_bg};color:{p_color};padding:1px 8px; | |
| border-radius:10px;font-size:11px;font-weight:600">{p_label}</span> | |
| <span style="font-size:11px;color:{cat_cfg['color']}">{cat_cfg['icon']} {item['category']}</span> | |
| </div> | |
| <div style="font-size:14px;font-weight:600;color:#1F2937;margin-bottom:4px">{item['label']}</div> | |
| <div style="font-size:12px;color:#6B7280">{item.get('evidence', '')}</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Save button | |
| if st.button("πΎ μ‘μ μμ΄ν μΌλ‘ μ μ₯", key="ai_save_triggers", use_container_width=True): | |
| _save_trigger_results(campaign_id, results, base_ctx) | |
| def _save_trigger_results(campaign_id: int, results: list[dict], base_ctx: dict): | |
| """Save trigger analysis results as action items.""" | |
| try: | |
| from core.supabase_client import get_supabase_client | |
| user_client = get_supabase_client() | |
| key_result = ( | |
| user_client.table("api_keys") | |
| .select("user_id") | |
| .limit(1) | |
| .execute() | |
| ) | |
| user_id = str(key_result.data[0]["user_id"]) if key_result.data else "unknown" | |
| result = save_action_items_batch( | |
| campaign_id=campaign_id, | |
| user_id=user_id, | |
| items=results, | |
| ) | |
| created = result.get("created", 0) | |
| skipped = result.get("skipped", 0) | |
| if result.get("error"): | |
| st.error(f"μ μ₯ μ€λ₯: {result['error']}") | |
| elif created > 0: | |
| st.success(f"β {created}κ° μ μ₯ μλ£ (μ€λ³΅ {skipped}κ° μ€ν΅)") | |
| st.session_state.pop("ai_trigger_results", None) | |
| st.rerun() | |
| else: | |
| st.info(f"λͺ¨λ νλͺ©μ΄ μ΄λ―Έ μ‘΄μ¬ν©λλ€ ({skipped}κ° μ€ν΅)") | |
| except Exception as e: | |
| st.error(f"μ μ₯ μ€ν¨: {e}") | |