GitHub Action
Sync from GitHub
ef78361
Raw
History Blame Contribute Delete
8.22 kB
"""๋ฆฌํฌํŠธ ํƒญ.
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