"""ChainShift Brand Risk Monitoring Dashboard v10.0. Feature Plugin Architecture: 새 기능 = features/ 디렉토리 생성 → 자동 등록. """ import streamlit as st from core.styles import DASHBOARD_CSS from sidebar import render_sidebar from registry import discover_features # ============================================================================= # Page Config # ============================================================================= st.set_page_config( page_title="ChainShift Dashboard", page_icon="⚡", layout="wide", initial_sidebar_state="expanded", ) st.markdown(DASHBOARD_CSS, unsafe_allow_html=True) st.title("ChainShift") st.caption("AI 검색 플랫폼에서 브랜드가 어떻게 언급되고 인용되는지 분석합니다") # ============================================================================= # Sidebar (인증 + 캠페인 선택) # ============================================================================= sidebar_result = render_sidebar() if not sidebar_result: st.stop() auth_info, selected_campaign_id, selected_campaign_display = sidebar_result # ============================================================================= # Feature Discovery + Rendering # ============================================================================= features = discover_features() if not features: st.error("등록된 Feature가 없습니다. features/ 디렉토리를 확인하세요.") st.stop() # Base context shared by all features base_ctx = { "api_key": auth_info.get("api_key"), "access_token": auth_info.get("access_token"), "campaign_id": selected_campaign_id, "campaign_name": selected_campaign_display, "user_email": auth_info.get("email"), } # Create tabs from discovered features tab_labels = [f"{f['config']['icon']} {f['config']['name']}" for f in features] tabs = st.tabs(tab_labels) for tab, feature in zip(tabs, features): with tab: try: feature["module"].render(base_ctx) except Exception as e: st.error(f"{feature['config']['name']} 로딩 실패: {e}") # ============================================================================= # Footer # ============================================================================= st.markdown("---") st.caption("ChainShift v10.0")