Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import requests | |
| import pandas as pd | |
| # =============================== | |
| # Firebase config from secrets.toml | |
| # =============================== | |
| FIREBASE_URL = st.secrets["firebase_database_url"] | |
| FIREBASE_AUTH = st.secrets["firebase_api_key"] | |
| # =============================== | |
| # CSS for better UI | |
| # =============================== | |
| st.markdown(""" | |
| <style> | |
| /* Push content down to avoid top bar overlap */ | |
| .block-container { | |
| padding-top: 80px; | |
| padding-left: 30px; | |
| padding-right: 30px; | |
| } | |
| /* Style headers */ | |
| h2 { | |
| color: #2E86AB; | |
| } | |
| h3 { | |
| color: #117A65; | |
| } | |
| /* Style buttons */ | |
| .stButton>button { | |
| background-color: #117A65; | |
| color: white; | |
| border-radius: 8px; | |
| padding: 0.4em 1em; | |
| font-weight: bold; | |
| } | |
| .stButton>button:hover { | |
| background-color: #0D5C48; | |
| } | |
| /* Style text areas */ | |
| textarea { | |
| border-radius: 8px; | |
| border: 1px solid #117A65; | |
| padding: 5px; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # =============================== | |
| # Helper functions | |
| # =============================== | |
| def firebase_get(path): | |
| url = f"{FIREBASE_URL}/{path}.json?auth={FIREBASE_AUTH}" | |
| try: | |
| res = requests.get(url) | |
| return res.json() if res.status_code == 200 else None | |
| except: | |
| return None | |
| def firebase_put(path, data): | |
| url = f"{FIREBASE_URL}/{path}.json?auth={FIREBASE_AUTH}" | |
| try: | |
| res = requests.put(url, json=data) | |
| return res.json() if res.status_code == 200 else None | |
| except: | |
| return None | |
| # =================================================== | |
| # GLOBAL LOGIN (applies to all roles) | |
| # =================================================== | |
| st.sidebar.title("π Professor Dashboard") | |
| if "logged_in" not in st.session_state: | |
| st.session_state.logged_in = False | |
| if not st.session_state.logged_in: | |
| st.markdown("<h2>ποΈ Professor Access</h2>", unsafe_allow_html=True) | |
| username = st.text_input("Username") | |
| password = st.text_input("Password", type="password") | |
| if st.button("Login"): | |
| if username == "master" and password == "master": | |
| st.session_state.logged_in = True | |
| st.success("Login successful!") | |
| st.rerun() | |
| else: | |
| st.error("Incorrect username or password") | |
| st.stop() # stop everything until login is completed | |
| # =================================================== | |
| # After login β Show menu | |
| # =================================================== | |
| menu = st.sidebar.selectbox("Select Mode", ["Professor Panel", "Student Evaluation"]) | |
| # =================================================== | |
| # PROFESSOR PANEL (Quiz Creator) | |
| # =================================================== | |
| if menu == "Professor Panel": | |
| st.header("π« Professor Panel") | |
| st.success("You are logged in as Professor") | |
| st.subheader("Create New Quiz") | |
| quiz_name = st.text_input("Quiz Name (Example: Quiz1)") | |
| questions = [] | |
| for i in range(1, 11): | |
| st.markdown(f"### Question {i}") | |
| q_text = st.text_input(f"Question content {i}", key=f"q{i}") | |
| options = [] | |
| for j in range(1, 5): | |
| opt = st.text_input(f"Option {j}", key=f"q{i}_opt{j}") | |
| options.append(opt) | |
| # Correct answer chosen by TEXT | |
| correct = st.selectbox( | |
| f"Correct answer for Question {i} (select by text)", | |
| options, | |
| key=f"q{i}_correct" | |
| ) | |
| questions.append({ | |
| "question": q_text, | |
| "options": options, | |
| "correct": correct | |
| }) | |
| if st.button("πΎ Save Quiz"): | |
| valid = all(q["question"] and all(q["options"]) for q in questions) | |
| if not quiz_name: | |
| st.error("Quiz name is required!") | |
| elif not valid: | |
| st.error("Please complete all questions and answers!") | |
| else: | |
| firebase_put(f"master_quizzes/{quiz_name}", {"questions": questions}) | |
| st.success(f"Quiz '{quiz_name}' saved successfully!") | |
| # =================================================== | |
| # STUDENT EVALUATION | |
| # =================================================== | |
| elif menu == "Student Evaluation": | |
| st.header("π Student Evaluation") | |
| # Refresh button | |
| if st.button("π Refresh Data"): | |
| st.cache_data.clear() | |
| st.rerun() | |
| # Load students | |
| students = firebase_get("student_quizzes") | |
| if not students: | |
| st.warning("No student data found.") | |
| st.stop() | |
| student_ids = list(students.keys()) | |
| selected_id = st.selectbox("Select Student ID", student_ids) | |
| info = students[selected_id] | |
| st.subheader("Student Information") | |
| st.write(f"**Name:** {info.get('Name', '')}") | |
| st.write(f"**Class:** {info.get('Class', '')}") | |
| # Identify quizzes | |
| quiz_keys = [k for k in info.keys() if k.startswith("Quiz")] | |
| # Show overview table | |
| table_data = [] | |
| for q in quiz_keys: | |
| qd = info[q] | |
| score = qd.get("Score", "") | |
| time = qd.get("Time", "") | |
| fb = qd.get("Feedback", "") | |
| fb_status = "Yes" if fb else "No" | |
| table_data.append({ | |
| "Quiz": q, | |
| "Score": score, | |
| "Time": time, | |
| "Feedbacked": fb_status | |
| }) | |
| st.subheader("Quiz Overview") | |
| df = pd.DataFrame(table_data) | |
| st.dataframe(df, use_container_width=True) | |
| # Feedback section | |
| st.subheader("Provide Feedback") | |
| choose_quiz = st.selectbox("Select a quiz to give feedback", quiz_keys) | |
| selected_quiz_data = info[choose_quiz] | |
| existing_fb = selected_quiz_data.get("Feedback", "") | |
| if existing_fb: | |
| st.info(f"π Existing Feedback:\n\n{existing_fb}") | |
| feedback = st.text_area("Enter new feedback") | |
| if st.button("π¨ Send Feedback"): | |
| firebase_put(f"student_quizzes/{selected_id}/{choose_quiz}/Feedback", feedback) | |
| st.success("Feedback sent successfully!") | |
| st.rerun() | |