from __future__ import annotations
import base64
import html
import json
from collections import defaultdict
from datetime import datetime
from pathlib import Path
from typing import Any
from backend.spaces_index import filter_public_spaces, get_category_distribution
from backend.storage import get_recent_feedback
CARD_DECORATIONS = ["compass", "camera", "lantern", "boot", "pine", "flower", "peak", "map"]
CARD_DECORATION_MARKS = {
"compass": "🧭",
"camera": "📷",
"lantern": "🏮",
"boot": "🥾",
"pine": "🌲",
"flower": "🌸",
"peak": "🏔",
"map": "🗺",
}
def safe(text: Any) -> str:
return html.escape("" if text is None else str(text))
PROJECT_ROOT = Path(__file__).resolve().parent.parent
BANNER_PATH = PROJECT_ROOT / "banner.png"
BADGE_PATH = PROJECT_ROOT / "hackathon-badge.png"
def _image_data_uri(path: Path) -> str:
data = path.read_bytes()
encoded = base64.b64encode(data).decode("ascii")
return f"data:image/png;base64,{encoded}"
BANNER_SRC = _image_data_uri(BANNER_PATH)
BADGE_SRC = _image_data_uri(BADGE_PATH)
def _js_literal(value: Any) -> str:
return html.escape(json.dumps(value, ensure_ascii=False), quote=True)
def _tags_text(tags: list[str] | None) -> str:
tags = [str(tag).strip() for tag in (tags or []) if str(tag).strip()]
return ", ".join(tags[:7])
def _group_feedback() -> dict[str, list[dict]]:
grouped: dict[str, list[dict]] = defaultdict(list)
for row in get_recent_feedback(limit=2000):
repo_id = str(row.get("repo_id", "")).strip()
if repo_id:
grouped[repo_id].append(row)
return grouped
def _human_datetime(value: str | None) -> str:
if not value:
return "Just now"
try:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
except Exception:
return str(value)
local = parsed.astimezone()
return local.strftime("%b %d, %Y at %I:%M %p").replace(" 0", " ")
COMMENTS_MODAL_HTML = """
"""
COMMENTS_MODAL_SCRIPT = """
"""
FIELD_GUIDE_SHELL_SCRIPT = """
"""
def render_page_shell(stats: dict, *, active_category: str = "All", active_query: str = "") -> str:
return f"""
"""
def render_footer_shell() -> str:
return """
""".format(badge_src=BADGE_SRC)
def _meta_button(text: str, *, css_class: str = "", attrs: str = "", tag: str = "button") -> str:
class_attr = f"card-action {css_class}".strip()
if tag == "a":
return f'{text}'
return f''
def render_space_card(
space: dict,
comments_by_repo: dict[str, list[dict]] | None = None,
*,
show_reason: bool = True,
enable_inline_comment: bool = False,
source_query: str = "",
tone_index: int = 0,
) -> str:
comments_by_repo = comments_by_repo or {}
repo_id = str(space.get("id", "")).strip()
comments = comments_by_repo.get(repo_id, [])
comment_count = len(comments)
reason = str(space.get("reason", "") or "").strip()
category = str(space.get("category", "Other") or "Other").strip()
track = str(space.get("track", "") or "").strip()
title = str(space.get("name", "") or "").strip()
likes = int(space.get("likes", 0) or 0)
tag_text = _tags_text(space.get("tags"))
deco_key = CARD_DECORATIONS[tone_index % len(CARD_DECORATIONS)]
deco_mark = CARD_DECORATION_MARKS[deco_key]
title_js = _js_literal(title)
repo_id_js = _js_literal(repo_id)
source_query_js = _js_literal(source_query)
open_url = safe(space.get("url", ""))
reason_html = ""
if show_reason and reason:
reason_html = f'Why it fits{safe(reason)}
'
inline_comment_html = ""
if enable_inline_comment and repo_id:
inline_comment_html = f"""
"""
category_chip = f'{safe(category)}' if category else ""
track_chip = f'{safe(track)}' if track else ""
comment_button = _meta_button(
f'💬 {comment_count}',
css_class="card-action--count",
attrs=f'onclick="window.bsqfOpenComments({title_js}, {repo_id_js})"',
)
like_chip = f'♥ {likes}'
open_button = _meta_button("Open Space ↗", css_class="card-action--open", attrs=f'href="{open_url}" target="_blank" rel="noreferrer"', tag="a")
return f"""
{category_chip}
{track_chip}
{like_chip}
{comment_button}
{open_button}
{safe(title)}
{reason_html}
{inline_comment_html}
{safe(tag_text)}
"""
def render_recommendation_cards(results: list[dict], *, show_reason: bool = False, source_query: str = "") -> str:
results = filter_public_spaces(results)
comments_by_repo = _group_feedback()
if not results:
return """
No spaces match this filter.
No matching spaces found.
Try to modify your search query
"""
cards = "\n".join(
render_space_card(
result,
comments_by_repo,
show_reason=show_reason,
enable_inline_comment=True,
source_query=source_query,
tone_index=index,
)
for index, result in enumerate(results)
)
return f"""
No spaces match this filter.
{cards}
"""
def render_category_section(spaces: list[dict], category: str) -> str:
spaces = filter_public_spaces(spaces)
comments_by_repo = _group_feedback()
if not spaces:
return """
No spaces match this filter.
No Spaces in this category
Nothing in the current index matches this category yet.
"""
cards = "\n".join(
render_space_card(
space,
comments_by_repo,
show_reason=False,
enable_inline_comment=False,
tone_index=index,
)
for index, space in enumerate(spaces)
)
return f"""
No spaces match this filter.
{cards}
"""
Comments