"""UI Components - Build HTML cards and tables with evaluation results."""
import pandas as pd
def build_product_cards(df, evaluations):
"""
Build HTML cards for products grouped by verdict.
Args:
df: DataFrame with product data
evaluations: List of evaluation dicts (same length as df)
Returns:
str: HTML string with product cards
"""
if df.empty:
return "
No products to display
"
# Add evaluation data to dataframe
df = df.copy()
df["verdict"] = [e.get("verdict", "possible") for e in evaluations]
df["notes"] = [e.get("notes", "") for e in evaluations]
df["requirements_met"] = [e.get("requirements_met", []) for e in evaluations]
# Check if there are actual requirements to display
has_requirements = any(e.get("requirements_met") for e in evaluations)
# Group by verdict
matches = df[df["verdict"] == "match"]
possibles = df[df["verdict"] == "possible"]
no_matches = df[df["verdict"] == "no_match"]
html_parts = [""]
# Show all products in a single grid - no verdict sections
# Just show the products with their confirmed features (green checkmarks)
all_products = pd.concat([matches, possibles, no_matches]) if not matches.empty or not possibles.empty or not no_matches.empty else pd.DataFrame()
if not all_products.empty:
html_parts.append("
Products ({})
".format(len(all_products)))
html_parts.append("
")
for _, product in all_products.iterrows():
html_parts.append(_build_card(product, "match", has_requirements))
html_parts.append("
")
html_parts.append("
")
return "\n".join(html_parts)
def _build_card(product, verdict, has_requirements=True):
"""Build a single product card."""
# Dark theme - all cards get dark gray background
colors = {
"bg": "#2d2d2d", # Dark gray background
"border": "#4a4a4a", # Slightly lighter gray border
"text": "#ffffff", # White text
"price": "#93c5fd" # Light blue for prices
}
# No verdict icons - checkmarks tell the story
icon = ""
title = product.get("title", "Unknown")
price = product.get("price", 0)
source = product.get("source", "")
rating = product.get("rating", None)
reviews = product.get("reviews", 0)
link = product.get("link", "")
thumbnail = product.get("thumbnail", "")
notes = product.get("notes", "")
requirements_met = product.get("requirements_met", [])
# Build requirements checklist - ONLY show confirmed features (met)
req_html = ""
if has_requirements and requirements_met:
confirmed_features = [r for r in requirements_met if r.get("status") == "met"]
if confirmed_features:
req_html = ""
for req_item in confirmed_features:
req_text = req_item.get("req", "")
req_html += f"
✓ {req_text}
" # Light green checkmark
req_html += "
"
# Clickable thumbnail
thumbnail_html = ""
if thumbnail and link:
thumbnail_html = f'
'
elif thumbnail:
thumbnail_html = f'
'
card_html = f"""
{thumbnail_html}
{title}
${price:.2f}
{source}
{f'
⭐ {rating} ({reviews} reviews)
' if rating else ''}
{req_html}
"""
return card_html
def build_comparison_table(df, evaluations):
"""
Build a comparison table with verdict column.
Args:
df: DataFrame with product data
evaluations: List of evaluation dicts
Returns:
pd.DataFrame: DataFrame ready for gr.Dataframe
"""
if df.empty:
return pd.DataFrame()
display_df = df.copy()
# Add verdict and notes columns
display_df["Verdict"] = [e.get("verdict", "possible") for e in evaluations]
display_df["AI Notes"] = [e.get("notes", "") for e in evaluations]
# Select and rename columns for display (no URL column)
columns_map = {
"title": "Title",
"price": "Price ($)",
"source": "Store",
"rating": "Rating",
"reviews": "Reviews",
"Verdict": "Verdict",
"AI Notes": "AI Notes"
}
display_df = display_df[[c for c in columns_map.keys() if c in display_df.columns]]
display_df = display_df.rename(columns=columns_map)
# Sort by verdict priority (match, possible, no_match)
verdict_order = {"match": 0, "possible": 1, "no_match": 2}
display_df["_sort"] = display_df["Verdict"].map(verdict_order)
display_df = display_df.sort_values("_sort").drop("_sort", axis=1)
return display_df.reset_index(drop=True)