File size: 5,410 Bytes
582bf6b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# 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,
    )