Spaces:
Sleeping
Sleeping
| """๋ฆฌํฌํธ ํญ. | |
| Feature๋ณ ๋ฏธ๋ฆฌ๋ณด๊ธฐ, HTML/CSV ๋ค์ด๋ก๋, ์ ์ฒด ๋ฆฌํฌํธ ์์ฑ. | |
| """ | |
| from datetime import datetime, timedelta | |
| import streamlit as st | |
| from core.api_client import ChainShiftClient | |
| from core.supabase_client import get_campaign_date_range | |
| from .utils import render_feature_section | |
| from . import full_report | |
| # Period presets: (label, days or None for "all") | |
| PERIOD_PRESETS = [ | |
| ("์ต๊ทผ 1์ผ", 1), | |
| ("์ต๊ทผ 7์ผ", 7), | |
| ("์ต๊ทผ 30์ผ", 30), | |
| ("์ต๊ทผ 90์ผ", 90), | |
| ("์ต๊ทผ 180์ผ", 180), | |
| ("์ ์ฒด ๊ธฐ๊ฐ", None), | |
| ("์ง์ ์ ํ", -1), | |
| ] | |
| def render(base_ctx: dict): | |
| """๋ฆฌํฌํธ ํญ ๋ ๋๋ง.""" | |
| st.markdown("##### ๋ฆฌํฌํธ") | |
| st.caption("๊ธฐ๊ฐ๋ณ AI ๊ฐ์์ฑ ๋ถ์ ๋ฆฌํฌํธ๋ฅผ ์์ฑํ๊ณ , HTML๋ก ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.") | |
| # Get campaign date range for presets | |
| campaign_date_range = get_campaign_date_range(base_ctx["campaign_id"]) | |
| if campaign_date_range: | |
| first_date_str, last_date_str = campaign_date_range | |
| first_date = datetime.strptime(first_date_str, "%Y-%m-%d") | |
| last_date = datetime.strptime(last_date_str, "%Y-%m-%d") | |
| total_days = (last_date - first_date).days + 1 | |
| else: | |
| first_date = datetime.now() - timedelta(days=30) | |
| last_date = datetime.now() | |
| first_date_str = first_date.strftime("%Y-%m-%d") | |
| last_date_str = last_date.strftime("%Y-%m-%d") | |
| total_days = 31 | |
| # Period selection | |
| start_date_str, end_date_str = _render_period_selector( | |
| first_date, last_date, first_date_str, last_date_str, total_days | |
| ) | |
| # Show selected period info | |
| selected_days = (datetime.strptime(end_date_str, "%Y-%m-%d") - datetime.strptime(start_date_str, "%Y-%m-%d")).days + 1 | |
| st.caption(f"๐ ์ ํ๋ ๊ธฐ๊ฐ: **{start_date_str} ~ {end_date_str}** ({selected_days}์ผ)") | |
| st.markdown("---") | |
| # 4 Sub-tabs for Features + 1 for Full Report | |
| report_tab_summary, report_tab_visibility, report_tab_citation, report_tab_full = st.tabs([ | |
| "๐ Executive Summary", | |
| "๐๏ธ Visibility & Content", | |
| "๐ Citation Analysis", | |
| "๐ ์ ์ฒด ๋ฆฌํฌํธ", | |
| ]) | |
| client = ChainShiftClient(api_key=base_ctx.get("api_key"), access_token=base_ctx.get("access_token")) | |
| # Tab 1: Executive Summary | |
| with report_tab_summary: | |
| render_feature_section( | |
| client=client, | |
| campaign_id=base_ctx["campaign_id"], | |
| feature_key="overview", | |
| title="๊ฐ์์ฑ ๊ฐ์", | |
| description="AI ํ๋ซํผ๋ณ ๋ธ๋๋ ๋ ธ์ถ ํํฉ๊ณผ ํต์ฌ ์งํ", | |
| start_date=start_date_str, | |
| end_date=end_date_str, | |
| api_key=base_ctx.get("api_key") or "", | |
| access_token=base_ctx.get("access_token") or "", | |
| ) | |
| # Tab 2: Visibility & Content | |
| with report_tab_visibility: | |
| render_feature_section( | |
| client=client, | |
| campaign_id=base_ctx["campaign_id"], | |
| feature_key="visibility", | |
| title="ํ๋ซํผ๋ณ ๊ฐ์์ฑ", | |
| description="ChatGPT, Gemini ๋ฑ AI ํ๋ซํผ๋ณ ์์ฌ vs ๊ฒฝ์์ฌ ๋ ธ์ถ ๋น๊ต", | |
| start_date=start_date_str, | |
| end_date=end_date_str, | |
| api_key=base_ctx.get("api_key") or "", | |
| access_token=base_ctx.get("access_token") or "", | |
| ) | |
| render_feature_section( | |
| client=client, | |
| campaign_id=base_ctx["campaign_id"], | |
| feature_key="content-types", | |
| title="์ฝํ ์ธ ์ ํ ๋ถํฌ", | |
| description="AI๊ฐ ์ธ์ฉํ๋ ์ฝํ ์ธ ์ ํ (๋ธ๋ก๊ทธ, ๋ด์ค, ๊ณต์ ์ฌ์ดํธ ๋ฑ)", | |
| start_date=start_date_str, | |
| end_date=end_date_str, | |
| api_key=base_ctx.get("api_key") or "", | |
| access_token=base_ctx.get("access_token") or "", | |
| ) | |
| render_feature_section( | |
| client=client, | |
| campaign_id=base_ctx["campaign_id"], | |
| feature_key="sentiment", | |
| title="๋ธ๋๋ ๊ฐ์ ๋ถ์", | |
| description="๋ธ๋๋๋ณ ๊ธ์ /๋ถ์ /์ค๋ฆฝ ๊ฐ์ ๋ถํฌ", | |
| start_date=start_date_str, | |
| end_date=end_date_str, | |
| api_key=base_ctx.get("api_key") or "", | |
| access_token=base_ctx.get("access_token") or "", | |
| ) | |
| # Tab 3: Citation Analysis | |
| with report_tab_citation: | |
| render_feature_section( | |
| client=client, | |
| campaign_id=base_ctx["campaign_id"], | |
| feature_key="citations", | |
| title="์ธ์ฉ ์ถ์ฒ ์์", | |
| description="AI ๋ต๋ณ์์ ๊ฐ์ฅ ๋ง์ด ์ธ์ฉ๋๋ ๋๋ฉ์ธ๊ณผ ์ถ์ฒ", | |
| start_date=start_date_str, | |
| end_date=end_date_str, | |
| api_key=base_ctx.get("api_key") or "", | |
| access_token=base_ctx.get("access_token") or "", | |
| ) | |
| render_feature_section( | |
| client=client, | |
| campaign_id=base_ctx["campaign_id"], | |
| feature_key="citation-trends", | |
| title="์ธ์ฉ ์ถ์ด", | |
| description="์๊ฐ์ ๋ฐ๋ฅธ ์ธ์ฉ ์ถ์ฒ ๋ณํ ํธ๋ ๋", | |
| start_date=start_date_str, | |
| end_date=end_date_str, | |
| api_key=base_ctx.get("api_key") or "", | |
| access_token=base_ctx.get("access_token") or "", | |
| ) | |
| render_feature_section( | |
| client=client, | |
| campaign_id=base_ctx["campaign_id"], | |
| feature_key="homepage-citations", | |
| title="ํํ์ด์ง ์ธ์ฉ๋ฅ ", | |
| description="์์ฌ ํํ์ด์ง๊ฐ AI ๋ต๋ณ์ ์ง์ ์ธ์ฉ๋๋ ๋น์จ", | |
| start_date=start_date_str, | |
| end_date=end_date_str, | |
| api_key=base_ctx.get("api_key") or "", | |
| access_token=base_ctx.get("access_token") or "", | |
| ) | |
| # Tab 4: Full Report | |
| with report_tab_full: | |
| full_report.render(client, base_ctx, start_date_str, end_date_str) | |
| def _render_period_selector( | |
| first_date: datetime, | |
| last_date: datetime, | |
| first_date_str: str, | |
| last_date_str: str, | |
| total_days: int, | |
| ) -> tuple[str, str]: | |
| """๊ธฐ๊ฐ ์ ํ UI ๋ ๋๋ง. (start_date, end_date) ๋ฐํ.""" | |
| col_period, col_date1, col_date2 = st.columns([1.5, 1, 1]) | |
| with col_period: | |
| period_options = [label for label, _ in PERIOD_PRESETS] | |
| selected_period = st.selectbox( | |
| "๋ถ์ ๊ธฐ๊ฐ", | |
| options=period_options, | |
| index=5, # Default to "์ ์ฒด ๊ธฐ๊ฐ" | |
| key="reports:period_select", | |
| help=f"์บ ํ์ธ ๋ฐ์ดํฐ: {first_date_str} ~ {last_date_str} (์ด {total_days}์ผ)", | |
| ) | |
| period_idx = period_options.index(selected_period) | |
| _, period_days = PERIOD_PRESETS[period_idx] | |
| if period_days == -1: # Custom selection | |
| with col_date1: | |
| report_start = st.date_input( | |
| "์์์ผ", | |
| value=first_date, | |
| min_value=first_date, | |
| max_value=last_date, | |
| key="reports:start_date", | |
| ) | |
| with col_date2: | |
| report_end = st.date_input( | |
| "์ข ๋ฃ์ผ", | |
| value=last_date, | |
| min_value=first_date, | |
| max_value=last_date, | |
| key="reports:end_date", | |
| ) | |
| return str(report_start), str(report_end) | |
| elif period_days is None: # All data | |
| with col_date1: | |
| st.text_input("์์์ผ", value=first_date_str, disabled=True, key="reports:start_display") | |
| with col_date2: | |
| st.text_input("์ข ๋ฃ์ผ", value=last_date_str, disabled=True, key="reports:end_display") | |
| return first_date_str, last_date_str | |
| else: # Preset days | |
| end_date = last_date | |
| start_date = max(first_date, end_date - timedelta(days=period_days - 1)) | |
| start_date_str = start_date.strftime("%Y-%m-%d") | |
| end_date_str = end_date.strftime("%Y-%m-%d") | |
| with col_date1: | |
| st.text_input("์์์ผ", value=start_date_str, disabled=True, key="reports:start_display") | |
| with col_date2: | |
| st.text_input("์ข ๋ฃ์ผ", value=end_date_str, disabled=True, key="reports:end_display") | |
| return start_date_str, end_date_str | |