debate_LMS / src /views /instructor_notes.py
raymondEDS
finishing instructor notes
eac70a0
import streamlit as st
from supabase import create_client, Client
import os
from datetime import datetime, date
import json
def init_supabase():
"""Initialize Supabase client"""
try:
url = st.secrets.get("SUPABASE_URL")
key = st.secrets.get("SUPABASE_KEY")
except:
url = os.getenv("SUPABASE_URL")
key = os.getenv("SUPABASE_KEY")
if not url or not key:
st.error("Supabase credentials not found.")
return None
return create_client(url, key)
def get_all_students():
"""Get all students from database"""
supabase = init_supabase()
if not supabase:
return []
try:
response = supabase.table('users').select('*').eq('role', 'student').execute()
return response.data if response.data else []
except Exception as e:
st.error(f"Error fetching students: {str(e)}")
return []
def get_instructor_id(username):
"""Get instructor ID from database by username"""
supabase = init_supabase()
if not supabase:
return None
try:
response = supabase.rpc('get_user_by_username', {'username_param': username}).execute()
if response.data:
return response.data[0]['id']
# Fallback: query the table directly
response = supabase.table('users').select('id').eq('username', username).execute()
if response.data:
return response.data[0]['id']
return None
except Exception as e:
st.error(f"Database error: {str(e)}")
return None
def save_instructor_notes(instructor_id, class_date, attendance_data, writing_skills_notes,
debate_skills_notes, parent_communication_notes, upcoming_events_notes, general_notes):
"""Save instructor notes to the database"""
supabase = init_supabase()
if not supabase:
return False
try:
data = {
'instructor_id': instructor_id,
'class_date': class_date,
'attendance_data': attendance_data,
'writing_skills_notes': writing_skills_notes,
'debate_skills_notes': debate_skills_notes,
'parent_communication_notes': parent_communication_notes,
'upcoming_events_notes': upcoming_events_notes,
'general_notes': general_notes
}
response = supabase.table('instructor_notes').insert(data).execute()
return True if response.data else False
except Exception as e:
st.error(f"Error saving notes: {str(e)}")
return False
def get_previous_notes(instructor_id, limit=10):
"""Get previous instructor notes"""
supabase = init_supabase()
if not supabase:
return []
try:
response = supabase.table('instructor_notes').select('*').eq('instructor_id', instructor_id).order('class_date', desc=True).limit(limit).execute()
return response.data if response.data else []
except Exception as e:
st.error(f"Error fetching previous notes: {str(e)}")
return []
def show_instructor_notes():
"""Show the instructor notes interface"""
st.title("πŸ“ Instructor Notes")
st.markdown("---")
# Check if current user is instructor
current_user = st.session_state.get('username')
if not current_user:
st.error("Please log in to access instructor notes.")
return
# Get current user's role
supabase = init_supabase()
if supabase:
try:
response = supabase.rpc('get_user_by_username', {'username_param': current_user}).execute()
if response.data:
user_role = response.data[0].get('role', 'student')
if user_role != 'instructor':
st.error("Access denied. Only instructors can access instructor notes.")
return
else:
st.error("User not found.")
return
except Exception as e:
st.error(f"Error checking user role: {str(e)}")
return
# Get instructor ID
instructor_id = get_instructor_id(current_user)
if not instructor_id:
st.error("Could not retrieve instructor information.")
return
# Get all students
students = get_all_students()
if not students:
st.error("No students found in the database.")
return
# Tabs for different functions
tab1, tab2 = st.tabs(["πŸ“ Take Notes", "πŸ“Š View Previous Notes"])
with tab1:
show_take_notes_form(instructor_id, students)
with tab2:
show_previous_notes(instructor_id)
def show_take_notes_form(instructor_id, students):
"""Show form to take instructor notes"""
st.subheader("πŸ“ Take Class Notes")
# Initialize session state for attendance tracking
if 'attendance_selections' not in st.session_state:
st.session_state.attendance_selections = {}
# Class date
class_date = st.date_input("Class Date", value=date.today(), key="class_date_input")
st.markdown("### πŸ“‹ Select Students Present")
st.markdown("Check the students who are present today:")
# Track which students are present using session state
present_students = []
for student in students:
# Create a unique key for each student's attendance
attendance_key = f"attendance_{student['id']}"
# Initialize the attendance state if not exists
if attendance_key not in st.session_state.attendance_selections:
st.session_state.attendance_selections[attendance_key] = False # Default to absent
# Checkbox for attendance
is_present = st.checkbox(
f"{student['full_name']} is present",
value=st.session_state.attendance_selections[attendance_key],
key=attendance_key,
on_change=lambda s=student, k=attendance_key: st.session_state.attendance_selections.update({k: not st.session_state.attendance_selections.get(k, True)})
)
# Update session state
st.session_state.attendance_selections[attendance_key] = is_present
if is_present:
present_students.append(student)
st.markdown(f"**Students Present:** {len(present_students)}")
# Create attendance data
attendance_data = {
"students": [
{
"student_id": student['id'],
"username": student['username'],
"full_name": student['full_name'],
"present": student in present_students
} for student in students
],
"total_present": len(present_students),
"total_absent": len(students) - len(present_students)
}
# Show notes section only for present students
if present_students:
st.markdown("### πŸ“ Student Notes")
st.markdown("Add notes for each present student:")
student_notes = {"students": []}
for student in present_students:
notes = st.text_area(
f"Notes for {student['full_name']}",
key=f"notes_{student['id']}",
placeholder="Enter notes about writing skills, debate performance, parent communication, etc...",
height=100
)
student_notes["students"].append({
"student_id": student['id'],
"username": student['username'],
"full_name": student['full_name'],
"notes": notes
})
# Use the same notes for all three categories (simplified)
writing_skills_notes = student_notes
debate_skills_notes = student_notes
parent_communication_notes = student_notes
else:
# Empty notes if no students present
writing_skills_notes = {"students": []}
debate_skills_notes = {"students": []}
parent_communication_notes = {"students": []}
st.markdown("### πŸ“… Upcoming Events")
upcoming_events_notes = {"tournaments": [], "important_dates": []}
# Simple event input
event_name = st.text_input("Event/Tournament Name (optional)", key="event_name")
if event_name:
event_date = st.date_input("Event Date", key="event_date")
event_notes = st.text_area("Event Notes (optional)", key="event_notes")
upcoming_events_notes["important_dates"].append({
"event": event_name,
"date": str(event_date),
"notes": event_notes
})
st.markdown("### πŸ“ General Notes")
general_notes = st.text_area("Any additional notes or observations:", height=100)
# Submit button
submit_button = st.button("πŸ’Ύ Save Notes")
if submit_button:
# Convert date to string for JSON serialization
class_date_str = class_date.strftime('%Y-%m-%d') if class_date else str(date.today())
if save_instructor_notes(instructor_id, class_date_str, attendance_data, writing_skills_notes,
debate_skills_notes, parent_communication_notes, upcoming_events_notes, general_notes):
st.success("Notes saved successfully!")
# Clear attendance selections after successful save
st.session_state.attendance_selections = {}
st.rerun()
else:
st.error("Failed to save notes. Please try again.")
def show_previous_notes(instructor_id):
"""Show previous instructor notes"""
st.subheader("πŸ“Š Previous Notes")
notes = get_previous_notes(instructor_id)
if not notes:
st.info("No previous notes found.")
return
# Create a selectbox for choosing which note to view
note_options = {f"{note['class_date']} - {len(note['attendance_data']['students'])} students": note for note in notes}
selected_note_display = st.selectbox("Choose a class session to view:", list(note_options.keys()))
if selected_note_display:
selected_note = note_options[selected_note_display]
st.markdown(f"**Class Date:** {selected_note['class_date']}")
st.markdown(f"**Created:** {selected_note['created_at']}")
# Display attendance
with st.expander("πŸ“‹ Attendance", expanded=True):
attendance = selected_note['attendance_data']
st.markdown(f"**Summary:** {attendance['total_present']} present, {attendance['total_absent']} absent")
for student in attendance['students']:
status = "βœ… Present" if student['present'] else "❌ Absent"
st.write(f"**{student['full_name']}:** {status}")
# Display student notes (simplified - all notes are the same)
if selected_note['writing_skills_notes'] and selected_note['writing_skills_notes']['students']:
with st.expander("πŸ“ Student Notes", expanded=False):
for student in selected_note['writing_skills_notes']['students']:
st.markdown(f"**{student['full_name']}:**")
if student['notes']:
st.write(f" {student['notes']}")
st.write("---")
# Display upcoming events
if selected_note['upcoming_events_notes']:
with st.expander("πŸ“… Upcoming Events", expanded=False):
events = selected_note['upcoming_events_notes']
if events.get('tournaments') and events['tournaments']:
st.markdown("**Tournaments:**")
for tournament in events['tournaments']:
st.write(f" **{tournament['name']}** - {tournament['date']}")
if tournament.get('location'):
st.write(f" Location: {tournament['location']}")
if tournament.get('notes'):
st.write(f" Notes: {tournament['notes']}")
st.write("---")
if events.get('important_dates') and events['important_dates']:
st.markdown("**Important Dates:**")
for event in events['important_dates']:
st.write(f" **{event['event']}** - {event['date']}")
if event.get('notes'):
st.write(f" Notes: {event['notes']}")
st.write("---")
# Display general notes
if selected_note['general_notes']:
with st.expander("πŸ“ General Notes", expanded=False):
st.write(selected_note['general_notes'])