Spaces:
Sleeping
Sleeping
| """Module 3 — Student Corner: CBT-informed stakes coach for Indian students. | |
| Flow: | |
| 1. Student picks an event type from quick buttons: exam / placement / viva / presentation / result / burnout | |
| 2. Student describes their situation in 1-3 sentences. | |
| 3. Crisis regex runs first. | |
| 4. Claude returns a structured response: acknowledge → distortion scan → 3 evidence-based prep tips → | |
| what NOT to do → 60-second grounding script → "if things get heavier" signpost. | |
| """ | |
| from __future__ import annotations | |
| import streamlit as st | |
| from backend.claude_client import chat | |
| from backend.i18n import claude_language_name, t | |
| from backend.safeguards import check_crisis, render_crisis_banner | |
| from backend.voice_widget import render_mic_button | |
| MODULE_NAME = "student_corner" | |
| EVENT_KEY = "student_event_type" | |
| SITUATION_KEY = "student_situation" | |
| RESPONSE_KEY = "student_response" | |
| EVENT_CHOICES = [ | |
| ("exam", "event_exam"), | |
| ("placement_interview", "event_placement"), | |
| ("viva", "event_viva"), | |
| ("presentation", "event_presentation"), | |
| ("result_day", "event_result"), | |
| ("general_burnout", "event_burnout"), | |
| ] | |
| def _init_state() -> None: | |
| if EVENT_KEY not in st.session_state: | |
| st.session_state[EVENT_KEY] = "exam" | |
| if SITUATION_KEY not in st.session_state: | |
| st.session_state[SITUATION_KEY] = "" | |
| if RESPONSE_KEY not in st.session_state: | |
| st.session_state[RESPONSE_KEY] = "" | |
| def render(lang: str) -> None: | |
| _init_state() | |
| st.header(t("student_header", lang)) | |
| st.caption(t("student_sub", lang)) | |
| # Event picker | |
| st.markdown(f"**{t('student_event_label', lang)}**") | |
| labels = [t(label_key, lang) for _, label_key in EVENT_CHOICES] | |
| event_values = [value for value, _ in EVENT_CHOICES] | |
| current_index = ( | |
| event_values.index(st.session_state[EVENT_KEY]) | |
| if st.session_state[EVENT_KEY] in event_values | |
| else 0 | |
| ) | |
| chosen_label = st.radio( | |
| "event", | |
| options=labels, | |
| index=current_index, | |
| horizontal=True, | |
| label_visibility="collapsed", | |
| key="student_event_radio", | |
| ) | |
| st.session_state[EVENT_KEY] = event_values[labels.index(chosen_label)] | |
| # Situation input | |
| render_mic_button(lang, target_aria_label="situation") | |
| situation = st.text_area( | |
| "situation", | |
| value=st.session_state[SITUATION_KEY], | |
| placeholder=t("student_input_placeholder", lang), | |
| label_visibility="collapsed", | |
| height=120, | |
| key="student_situation_input", | |
| ) | |
| if st.button(t("student_send_button", lang), type="primary", key="student_send_button"): | |
| if situation.strip(): | |
| st.session_state[SITUATION_KEY] = situation | |
| if check_crisis(situation): | |
| render_crisis_banner(lang) | |
| return | |
| user_text = ( | |
| f"event_type: {st.session_state[EVENT_KEY]}\n" | |
| f"situation: {situation}" | |
| ) | |
| with st.spinner("…"): | |
| try: | |
| reply = chat( | |
| module=MODULE_NAME, | |
| user_text=user_text, | |
| language_name=claude_language_name(lang), | |
| max_tokens=2400, | |
| ) | |
| except Exception as e: | |
| reply = ( | |
| "I couldn't reach my language model right now. " | |
| "For immediate support call **Tele-MANAS on 14416** (Government of India, free, 24×7, 20+ Indian languages) " | |
| "or **iCall** on 9152987821 (Mon–Sat 8 AM–10 PM).\n\n" | |
| f"_(Technical detail: {e})_" | |
| ) | |
| st.session_state[RESPONSE_KEY] = reply | |
| if st.session_state[RESPONSE_KEY]: | |
| st.divider() | |
| st.markdown(st.session_state[RESPONSE_KEY]) | |