import streamlit as st from db import ( fetch_room_names, fetch_room_names_by_owner, topic_owner_column_available, topic_entry_code_column_available, upsert_topic_room, ) from validators import ( normalize_user_text, validate_entry_code, validate_opinion_content, validate_room_name, ) from utils import log_audit from config import MAX_ROOM_NAME_LEN, MAX_TOPIC_LEN, MAX_ENTRY_CODE_LEN from components.teacher_auth import render_teacher_auth def _reset_joined_state(): st.session_state['joined'] = False st.session_state['teacher_auth'] = False st.session_state['admin_auth'] = False st.session_state['teacher_id'] = "" st.session_state.pop('_admin_redirected', None) def render_sidebar(supabase) -> dict: with st.sidebar: st.header("πŸ‘€ 접속 κΆŒν•œ") user_role = st.radio("λͺ¨λ“œ 선택", ["학생", "ꡐ사"], on_change=_reset_joined_state) st.divider() try: all_rooms = fetch_room_names(supabase) except Exception: all_rooms = [] room_name = "" teacher_auth = False admin_auth = False student_number = "" if user_role == "ꡐ사": render_teacher_auth(supabase) teacher_auth = st.session_state['teacher_auth'] admin_auth = st.session_state['admin_auth'] teacher_id_for_scope = st.session_state.get("teacher_id", "") if teacher_auth: existing_rooms = all_rooms if admin_auth else ( fetch_room_names_by_owner(supabase, teacher_id_for_scope) if topic_owner_column_available() else [] ) if not admin_auth and not topic_owner_column_available(): st.warning("ꡐ사별 λ°© 쑰회λ₯Ό μœ„ν•΄ topic.created_by_teacher_id(ꢌμž₯) λ˜λŠ” topic.created_by 컬럼이 ν•„μš”ν•©λ‹ˆλ‹€.") room_opt = st.radio("λ°© 관리", ["κΈ°μ‘΄ λ°© 선택", "μƒˆ λ°© λ§Œλ“€κΈ°"]) if room_opt == "κΈ°μ‘΄ λ°© 선택": if existing_rooms: current = st.session_state.get('current_room', '') default_idx = existing_rooms.index(current) if current in existing_rooms else 0 room_name = st.selectbox("ν† λ‘ /ν† μ˜λ°© λͺ©λ‘", existing_rooms, index=default_idx) else: st.info("아직 κ°œμ„€λœ 방이 μ—†μŠ΅λ‹ˆλ‹€. 'μƒˆ λ°© λ§Œλ“€κΈ°'λ₯Ό 선택해 첫 번째 방을 λ§Œλ“€μ–΄λ³΄μ„Έμš”.") room_name = "" else: new_room = st.text_input("μƒˆλ‘œ λ§Œλ“€ λ°© 이름 (예: 1ν•™λ…„ 3반)") new_title = st.text_input("주제 직접 μž…λ ₯ (예: 인곡지λŠ₯ 윀리)") new_mode = st.radio("μ§„ν–‰ 방식", ["βš”οΈ 찬반 ν† λ‘ ", "πŸ’‘ 자유 ν† μ˜"], horizontal=True) new_pw = st.text_input("πŸ”’ 학생 μž…μž₯용 μ•”ν˜Έ (λΉ„μ›Œλ‘λ©΄ 곡개방)") if st.button("μƒˆ λ°© κ°œμ„€ν•˜κΈ°", type="primary"): room_ok, safe_new_room, _, room_error_message = validate_room_name(new_room, max_len=MAX_ROOM_NAME_LEN) title_ok, safe_new_title, _, title_error_message = validate_opinion_content(new_title, max_len=MAX_TOPIC_LEN) entry_ok, safe_new_pw, _, entry_error_message = validate_entry_code(new_pw, max_len=MAX_ENTRY_CODE_LEN) can_store_room_pw = topic_entry_code_column_available() if not room_ok: st.error(f"❌ {room_error_message}") elif not title_ok: st.error(f"❌ {title_error_message}") elif not entry_ok: st.error(f"❌ {entry_error_message}") elif safe_new_pw and not can_store_room_pw: st.error("ν˜„μž¬ DB κ΅¬μ‘°μ—μ„œλŠ” λ°© λΉ„λ°€λ²ˆν˜Έ μ €μž₯을 μ§€μ›ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.") elif safe_new_room and safe_new_title: res = upsert_topic_room( supabase=supabase, room_name=safe_new_room, title=safe_new_title, mode=new_mode, entry_code=safe_new_pw, created_by=teacher_id_for_scope, ) if res is not None: fetch_room_names.clear() fetch_room_names_by_owner.clear() st.session_state['current_room'] = safe_new_room st.toast(f"'{safe_new_room}' 방이 κ°œμ„€λ˜μ—ˆμŠ΅λ‹ˆλ‹€!", icon="πŸŽ‰") st.rerun() room_name = "" else: st.session_state['teacher_auth'] = False st.session_state['admin_auth'] = False st.session_state['teacher_id'] = "" if st.session_state.get('page') == "admin_approval": st.session_state['page'] = "lobby" _joined = st.session_state.get('joined', False) student_number = st.text_input( "ν•™λ²ˆ", key="student_number_input", placeholder="예: 1101", disabled=_joined, help="λ°© μž…μž₯ ν›„μ—λŠ” ν•™λ²ˆμ„ λ³€κ²½ν•  수 μ—†μŠ΅λ‹ˆλ‹€." if _joined else None, ) if all_rooms: room_name = st.selectbox("🏠 접속할 λ°© 선택", all_rooms) else: st.warning("μ„ μƒλ‹˜μ΄ 아직 μ—΄μ–΄λ‘” 방이 μ—†μŠ΅λ‹ˆλ‹€.") room_name = "" student_name = normalize_user_text(student_number, max_len=20) if user_role == "학생" else "ꡐ사" if room_name and room_name != st.session_state['current_room']: prev_room = st.session_state['current_room'] st.session_state['current_room'] = room_name st.session_state['ai_hint_text'] = "" st.session_state['ai_report_text'] = "" st.session_state.pop('_admin_redirected', None) if st.session_state['joined']: st.session_state['joined'] = False log_audit("room_switched_to_lobby", room_name=room_name, actor_name=student_name, role=user_role, previous_room=prev_room) st.rerun() if st.session_state['joined']: st.divider() if st.button("πŸšͺ λ°© λ‚˜κ°€κΈ° (λŒ€κΈ°μ‹€λ‘œ)"): st.session_state['joined'] = False st.session_state.pop('_admin_redirected', None) st.rerun() return { 'user_role': user_role, 'room_name': room_name, 'teacher_auth': teacher_auth, 'admin_auth': admin_auth, 'student_name': student_name, 'student_number': student_number, }