Trivia5 / src /utils /ui_components.py
Bharath370's picture
Upload 102 files
582bf6b verified
# utils/ui_components.py
import streamlit as st
import plotly.graph_objects as go
from config.settings import BADGES
from config.themes import THEMES
def apply_custom_theme(theme_name: str):
"""Applies a custom theme using CSS variables."""
theme = THEMES.get(theme_name, THEMES["default"])
css_vars = {
"--primary-color": theme["primary_color"],
"--background-color": theme["background_color"],
"--secondary-background-color": theme["secondary_background_color"],
"--text-color": theme["text_color"],
"--font": theme["font"],
"--card-background": theme.get("card_background", "#FFFFFF"),
"--shadow-light": theme.get("shadow_light", "0 4px 15px rgba(0, 0, 0, 0.05)"),
"--shadow-medium": theme.get("shadow_medium", "0 8px 30px rgba(0, 0, 0, 0.1)"),
"--highlight-color": theme.get("highlight_color", theme["primary_color"]),
}
css_vars_str = "\n".join([f"{key}: {value};" for key, value in css_vars.items()])
css = f"""
<style>
:root {{ {css_vars_str} }}
.stApp {{ background-color: var(--background-color); color: var(--text-color); }}
.stSidebar {{ background-color: var(--secondary-background-color); }}
.stButton>button {{ background-color: var(--primary-color); color: white; box-shadow: var(--shadow-light); }}
.stButton>button:hover {{ background-color: var(--secondary-color); box-shadow: var(--shadow-medium); }}
/* Add other theme styles here */
</style>
"""
st.markdown(css, unsafe_allow_html=True)
def display_user_stats(stats: dict, ui: dict):
"""Displays user statistics in a dashboard format."""
cols = st.columns(4)
with cols[0]:
st.metric(ui.get("total_score", "Total Score"), f"{stats.get('total_score', 0):,}")
with cols[1]:
st.metric(ui.get("quizzes", "Quizzes Played"), stats.get("quizzes_completed", 0))
with cols[2]:
st.metric(ui.get("current_streak", "Current Streak"), f"πŸ”₯ {stats.get('current_streak', 0)}")
with cols[3]:
st.metric(ui.get("best_streak", "Best Streak"), f"⭐ {stats.get('best_streak', 0)}")
def display_badges(earned_badges: list, ui: dict):
"""Displays earned badges."""
if not earned_badges:
return
st.markdown(f"### πŸ† {ui.get('your_badges', 'Your Badges')}")
cols = st.columns(len(earned_badges))
for i, badge_id in enumerate(earned_badges):
badge = BADGES.get(badge_id)
if badge:
with cols[i]:
st.markdown(f"<div style='text-align: center;'><span style='font-size: 50px;'>{badge['icon']}</span><br><b>{ui.get(badge['name'].lower(), badge['name'])}</b></div>", unsafe_allow_html=True)
def create_progress_chart(stats: dict, ui: dict) -> go.Figure:
"""Creates a progress chart for the user."""
history = stats.get("quiz_history", [])
if not history:
return go.Figure()
dates = [item["timestamp"] for item in history]
scores = [item["percentage"] for item in history]
fig = go.Figure()
fig.add_trace(go.Scatter(x=dates, y=scores, mode="lines+markers", name=ui.get("score", "Score") + " %"))
fig.update_layout(
title=ui.get("quiz_performance_over_time", "Quiz Performance Over Time"),
xaxis_title=ui.get("date", "Date"),
yaxis_title=f"{ui.get('score', 'Score')} (%)",
yaxis_range=[0, 100],
)
return fig
def animated_success(message: str):
"""Displays an animated success message."""
st.markdown(f"<div class='pop-in'>{st.success(message)}</div>", unsafe_allow_html=True)
def create_quiz_card(question: str, options: list, key: str):
"""Creates a card for a multiple-choice question."""
st.markdown(f"<div style='background-color: var(--card-background); padding: 20px; border-radius: 10px; box-shadow: var(--shadow-light);'>", unsafe_allow_html=True)
st.subheader(question)
st.session_state[key] = st.radio(
"Select your answer:",
options,
index=None,
key=f"{key}_radio",
label_visibility="collapsed",
)
st.markdown("</div>", unsafe_allow_html=True)
def render_flashcard(front_content: str, back_content: str, is_flipped: bool):
"""Renders a flippable flashcard."""
card_style = "width: 100%; height: 300px; perspective: 1000px;"
flipper_style = f'position: relative; width: 100%; height: 100%; transition: transform 0.6s; transform-style: preserve-3d; transform: {"rotateY(180deg)" if is_flipped else "none"};'
face_style = "position: absolute; width: 100%; height: 100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; display: flex; justify-content: center; align-items: center; padding: 20px; border-radius: 10px; box-shadow: var(--shadow-light);"
front_style = f"{face_style} background-color: var(--primary-color); color: white;"
back_style = f"{face_style} background-color: var(--card-background); color: var(--text-color); transform: rotateY(180deg);"
st.markdown(
f"<div style='{card_style}'><div style='{flipper_style}'>"
f"<div style='{front_style}'><div>{front_content}</div></div>"
f"<div style='{back_style}'><div>{back_content}</div></div>"
f"</div></div>",
unsafe_allow_html=True,
)