import flet as ft import requests import threading import asyncio import websockets from websockets import connect # Ensure this is imported import json from datetime import datetime from pages.student_main_page import student_main_page def main_page(page: ft.Page): page.clean() page.theme_mode = ft.ThemeMode.LIGHT session = page.session.get("access_token") if not session: page.go("/login") # Redirect to login if no session def is_student(): url = 'http://awesom-o.org:8000/check_role' headers = { 'accept': 'application/json', 'Content-Type': 'application/json' } session_id = page.session.get("access_token") if not session_id: return None data = {'session_id': session_id} try: response = requests.post(url, json=data, headers=headers) response.raise_for_status() role = response.json() if role and 'role' in role and 'role' in role['role']: if role['role']['role'] == "student": role = "s" return role elif role['role']['role'] == "teacher": role = "t" return role print("Unexpected response structure:", role) return None except requests.exceptions.RequestExceptin as error: print("Error during role check:", error) return None page.title = "Room Information" page.vertical_alignment = ft.MainAxisAlignment.START # Align all content to the top if is_student() == "s": student_main_page(page) elif is_student() == "t": async def fetch_room_data(session_id: str, update_room_list): uri = "ws://localhost:8000/ws/teacher/open_rooms" headers = {"session-id": session_id} # Add session ID to headers async with websockets.connect(uri, extra_headers=headers) as websocket: print("WebSocket connected") try: while True: # Receive data from the WebSocket data = await websocket.recv() room_data = json.loads(data) open_rooms = room_data.get("open_rooms", []) # Update the room list update_room_list(open_rooms) except websockets.ConnectionClosed: print("WebSocket connection closed") except Exception as e: print(f"WebSocket error: {e}") # Function to fetch students in a room def fetch_students_in_room(unique_id: str, session_id: str): url = f"http://awesom-o.org:8000/teacher/room_students/?unique_id={unique_id}" headers = {"accept": "application/json", "Content-Type": "application/json"} data = {"session_id": session_id} try: response = requests.post(url, json=data, headers=headers) response.raise_for_status() return response.json() except requests.RequestException as e: print(f"Error fetching students: {e}") return None # Function to delete a room def delete_room(unique_id: str, session_id: str): url = f"http://awesom-o.org:8000/teacher/delete_room/?unique_id={unique_id}" headers = {"accept": "application/json", "Content-Type": "application/json"} data = {"session_id": session_id} try: response = requests.delete(url, json=data, headers=headers) response.raise_for_status() return True except requests.RequestException as e: print(f"Error deleting room: {e}") return False # Main Flet app page.title = "Room Management" page.vertical_alignment = ft.MainAxisAlignment.START # Align content to the top page.horizontal_alignment = ft.CrossAxisAlignment.CENTER page.padding = 20 page.scroll = "adaptive" # Check if the user is logged in session_id = page.session.get("access_token") if not session_id: page.go("/login") # Redirect to login if no session # Search field search_field = ft.TextField(label="Search", expand=True) # Icon button to navigate to "/create" page create_button = ft.IconButton( icon=ft.icons.ADD, on_click=lambda _: page.go("/create"), ) # Container for the room list room_container = ft.Column(scroll=ft.ScrollMode.AUTO, expand=True) # Function to update the room list def update_room_list(rooms): room_container.controls.clear() for room in rooms: room_name = room.get("room_name", "Unknown Room") room_info = room.get("info", "") location = room.get("location", "") teacher_name = room.get("teacher_name", "") max_students = room.get("max_students", 0) current_students = room.get("current_students", 0) unique_id = room.get("unique_id", "") # Create a clickable room card room_card = ft.GestureDetector( content=ft.Card( content=ft.Container( content=ft.Column( [ # Top line: room_name, room_info, location ft.Row( [ ft.Text(f"{room_name}", size=20), ft.Text(f"{room_info}", size=16), ft.Text(f"| {location}", size=16), ], spacing=5, ), # Teacher line ft.Text(f"Teacher: {teacher_name}", size=16), # Capacity line ft.Text(f"Capacity: {current_students}/{max_students}", size=16), ], spacing=10, ), padding=20, ), margin=10, elevation=5, ), on_tap=lambda e, unique_id=unique_id: open_room_dialog(unique_id), ) room_container.controls.append(room_card) if not rooms: room_container.controls.append(ft.Text("No open rooms available.", size=18)) page.update() # Function to open the room dialog def open_room_dialog(unique_id: str): # Fetch students in the room students_data = fetch_students_in_room(unique_id, session_id) if not students_data: page.snack_bar = ft.SnackBar(ft.Text("Failed to fetch students.")) page.snack_bar.open = True page.update() return students = students_data.get("students", []) if students != None: students_list = ft.Column( [ft.Text(f"Student: {student}") for student in students], scroll=ft.ScrollMode.AUTO, expand=True, ) else: students_list = ft.Column(ft.Text(f"There are no students who joined your Room"), scroll=ft.ScrollMode.AUTO, expand=True, ) # Confirmation dialog for deleting the room def open_delete_confirmation_dialog(): page.close(dialog) def confirm_delete(e): if delete_room(unique_id, session_id): page.snack_bar = ft.SnackBar(ft.Text("Room deleted successfully.")) page.snack_bar.open = True page.update() page.close(confirm_dialog) page.update() else: page.snack_bar = ft.SnackBar(ft.Text("Failed to delete room.")) page.snack_bar.open = True page.update() confirm_dialog = ft.AlertDialog( title=ft.Text("Are you sure you want to delete this room?"), actions=[ ft.TextButton("No", on_click=lambda e: page.close(confirm_dialog)), ft.TextButton("Yes", on_click=confirm_delete), ], ) page.dialog = confirm_dialog confirm_dialog.open = True page.update() # Room dialog dialog = ft.AlertDialog( title=ft.Text("Room Details"), content=students_list, actions=[ ft.TextButton("Close", on_click=lambda e: page.close(dialog)), ft.TextButton("Delete Room", on_click=lambda e: open_delete_confirmation_dialog()), ], ) page.dialog = dialog dialog.open = True page.update() # WebSocket listener for real-time updates async def listen_for_updates(): while True: try: await fetch_room_data(session_id, update_room_list) except Exception as e: print(f"WebSocket connection error: {e}. Reconnecting in 5 seconds...") await asyncio.sleep(5) # Wait before reconnecting # Top bar layout top_bar = ft.Row( [ search_field, create_button, ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN, vertical_alignment=ft.CrossAxisAlignment.CENTER, ) # Add components to the page page.add( top_bar, room_container, ) # Start the WebSocket listener page.run_task(listen_for_updates) else: page.go("/login")