Spaces:
Sleeping
Sleeping
File size: 4,840 Bytes
e78b10d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# 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"""
<style>
:root {{
--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"]};
}}
/* Apply background color to the main Streamlit elements */
.stApp {{
background-color: var(--background-color);
color: var(--text-color);
}}
.stSidebar {{
background-color: var(--secondary-background-color);
}}
</style>
"""
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"<div style='text-align: center; padding: 10px; border-radius: 10px; background-color: var(--secondary-background-color);'>",
unsafe_allow_html=True,
)
st.markdown(
f"<span style='font-size: 50px;'>{badge['icon']}</span>",
unsafe_allow_html=True,
)
st.markdown(f"**{badge['name']}**")
st.markdown(f"</div>", 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"<div style='{{card_style}}'><div style='{{flipper_style}}'> \
<div style='{{front_style}}'><div>{front_content}</div></div> \
<div style='{{back_style}}'><div>{back_content}</div></div> \
</div></div>",
unsafe_allow_html=True,
)
|