# 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 = f"""
"""
st.markdown(css, unsafe_allow_html=True)
def display_user_stats(stats: dict):
"""Displays user statistics in a dashboard format."""
cols = st.columns(4)
with cols[0]:
st.metric("Total Score", f"{stats.get('total_score', 0):,}")
with cols[1]:
st.metric("Quizzes Played", stats.get("quizzes_completed", 0))
with cols[2]:
st.metric("Current Streak", f"🔥 {stats.get('current_streak', 0)}")
with cols[3]:
st.metric("Best Streak", f"⭐ {stats.get('best_streak', 0)}")
def display_badges(earned_badges: list):
"""Displays earned badges."""
if not earned_badges:
return
st.markdown("### 🏆 Your Badges")
cols = st.columns(len(BADGES))
for i, badge_id in enumerate(earned_badges):
badge = BADGES.get(badge_id)
if badge:
with cols[i]:
st.markdown(
f"
",
unsafe_allow_html=True,
)
st.markdown(
f"{badge['icon']}",
unsafe_allow_html=True,
)
st.markdown(f"**{badge['name']}**")
st.markdown(f"
", unsafe_allow_html=True)
def create_progress_chart(stats: 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="Score %"))
fig.update_layout(
title="Quiz Performance Over Time",
xaxis_title="Date",
yaxis_title="Score (%)",
yaxis_range=[0, 100],
)
return fig
def animated_success(message: str):
"""Displays an animated success message."""
st.success(message)
def create_quiz_card(question: str, options: list):
"""Creates a card for a multiple-choice question."""
st.subheader(question)
answer = st.radio(
"Select your answer:", options, index=None, label_visibility="collapsed"
)
return answer
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: 0 4px 8px 0 rgba(0,0,0,0.2);
"""
front_style = (
f"{{face_style}} background-color: var(--primary-color); color: white;"
)
back_style = f"{{face_style}} background-color: var(--secondary-background-color); color: var(--text-color); transform: rotateY(180deg);"
st.markdown(
f"",
unsafe_allow_html=True,
)