import streamlit as st import requests import json # Backend URL BASE_URL = "https://testys-clearance-sys.hf.space" # Session state for auth if 'token' not in st.session_state: st.session_state.token = None if 'user' not in st.session_state: st.session_state.user = None def login(username, password): response = requests.post(f"{BASE_URL}/token", data={"username": username, "password": password}) if response.status_code == 200: data = response.json() st.session_state.token = data['access_token'] st.session_state.user = username st.success("Logged in successfully!") else: st.error(f"Login failed: {response.text}") def logout(): st.session_state.token = None st.session_state.user = None st.success("Logged out!") def api_call(method, endpoint, params=None, data=None, headers=None): url = f"{BASE_URL}{endpoint}" if params: url += '?' + '&'.join([f"{k}={v}" for k, v in params.items()]) if headers is None: headers = {} if st.session_state.token: headers['Authorization'] = f"Bearer {st.session_state.token}" if method == 'GET': response = requests.get(url, headers=headers) elif method == 'POST': response = requests.post(url, json=data, headers=headers) elif method == 'PUT': response = requests.put(url, json=data, headers=headers) elif method == 'DELETE': response = requests.delete(url, headers=headers) return response st.title("Clearance System Frontend") if st.session_state.token is None: st.header("Login") username = st.text_input("Username") password = st.text_input("Password", type="password") if st.button("Login"): login(username, password) else: st.write(f"Logged in as: {st.session_state.user}") if st.button("Logout"): logout() # Navigation page = st.sidebar.selectbox("Select Page", [ "Students", "Users", "Tags", "Devices", "Clearance", "RFID", "Scanners", "Profile" ]) if page == "Students": st.header("Student Management") action = st.selectbox("Action", ["List", "Create", "Lookup", "Read Single", "Update", "Delete"]) if action == "List": skip = st.number_input("Skip", min_value=0, value=0) limit = st.number_input("Limit", min_value=1, value=100) if st.button("Get Students"): params = {"skip": skip, "limit": limit} response = api_call('GET', '/admin/students/', params=params) if response.status_code == 200: students = response.json() st.json(students) else: st.error(f"Failed to fetch students: {response.text}") elif action == "Create": full_name = st.text_input("Full Name") matric_no = st.text_input("Matric No") email = st.text_input("Email") department = st.selectbox("Department", ["Computer Science", "Engineering", "Business Administration", "Law", "Medicine"]) password = st.text_input("Password", type="password") if st.button("Create Student"): data = { "full_name": full_name, "matric_no": matric_no, "email": email, "department": department, "password": password } response = api_call('POST', '/admin/students/', data=data) if response.status_code == 201: st.success("Student created!") st.json(response.json()) else: st.error(f"Failed to create student: {response.text}") elif action == "Lookup": matric_no = st.text_input("Matric No (optional)") tag_id = st.text_input("Tag ID (optional)") if st.button("Lookup Student"): if not matric_no and not tag_id: st.error("Provide either Matric No or Tag ID") else: params = {} if matric_no: params["matric_no"] = matric_no if tag_id: params["tag_id"] = tag_id response = api_call('GET', '/admin/students/lookup', params=params) if response.status_code == 200: st.json(response.json()) else: st.error(f"Failed to lookup student: {response.text}") elif action == "Read Single": student_id = st.number_input("Student ID", min_value=1) if st.button("Get Student"): response = api_call('GET', f'/admin/students/{student_id}') if response.status_code == 200: st.json(response.json()) else: st.error(f"Failed to fetch student: {response.text}") elif action == "Update": student_id = st.number_input("Student ID", min_value=1) full_name = st.text_input("Full Name (optional)") email = st.text_input("Email (optional)") department = st.selectbox("Department (optional)", [None, "Computer Science", "Engineering", "Business Administration", "Law", "Medicine"]) if st.button("Update Student"): data = {} if full_name: data["full_name"] = full_name if email: data["email"] = email if department: data["department"] = department if not data: st.error("Provide at least one field to update") else: response = api_call('PUT', f'/admin/students/{student_id}', data=data) if response.status_code == 200: st.success("Student updated!") st.json(response.json()) else: st.error(f"Failed to update student: {response.text}") elif action == "Delete": student_id = st.number_input("Student ID", min_value=1) if st.button("Delete Student"): response = api_call('DELETE', f'/admin/students/{student_id}') if response.status_code == 200: st.success("Student deleted!") st.json(response.json()) else: st.error(f"Failed to delete student: {response.text}") elif page == "Users": st.header("User Management") action = st.selectbox("Action", ["List", "Create", "Read Single", "Update", "Delete"]) if action == "List": skip = st.number_input("Skip", min_value=0, value=0) limit = st.number_input("Limit", min_value=1, value=100) if st.button("Get Users"): params = {"skip": skip, "limit": limit} response = api_call('GET', '/admin/users/', params=params) if response.status_code == 200: users = response.json() st.json(users) else: st.error(f"Failed to fetch users: {response.text}") elif action == "Create": username = st.text_input("Username") email = st.text_input("Email") full_name = st.text_input("Full Name") password = st.text_input("Password", type="password") role = st.selectbox("Role", ["admin", "staff"]) department = st.selectbox("Department (optional)", [None, "Computer Science", "Engineering", "Business Administration", "Law", "Medicine"]) if st.button("Create User"): data = { "username": username, "email": email, "full_name": full_name, "password": password, "role": role, "department": department } response = api_call('POST', '/admin/users/', data=data) if response.status_code == 201: st.success("User created!") st.json(response.json()) else: st.error(f"Failed to create user: {response.text}") elif action == "Read Single": user_id = st.number_input("User ID", min_value=1) if st.button("Get User"): response = api_call('GET', f'/admin/users/{user_id}') if response.status_code == 200: st.json(response.json()) else: st.error(f"Failed to fetch user: {response.text}") elif action == "Update": user_id = st.number_input("User ID", min_value=1) username = st.text_input("Username (optional)") email = st.text_input("Email (optional)") full_name = st.text_input("Full Name (optional)") password = st.text_input("Password (optional)", type="password") role = st.selectbox("Role (optional)", [None, "admin", "staff"]) department = st.selectbox("Department (optional)", [None, "Computer Science", "Engineering", "Business Administration", "Law", "Medicine"]) if st.button("Update User"): data = {} if username: data["username"] = username if email: data["email"] = email if full_name: data["full_name"] = full_name if password: data["password"] = password if role: data["role"] = role if department: data["department"] = department if not data: st.error("Provide at least one field to update") else: response = api_call('PUT', f'/admin/users/{user_id}', data=data) if response.status_code == 200: st.success("User updated!") st.json(response.json()) else: st.error(f"Failed to update user: {response.text}") elif action == "Delete": user_id = st.number_input("User ID", min_value=1) if st.button("Delete User"): response = api_call('DELETE', f'/admin/users/{user_id}') if response.status_code == 200: st.success("User deleted!") st.json(response.json()) else: st.error(f"Failed to delete user: {response.text}") elif page == "Tags": st.header("Tag Management") action = st.selectbox("Action", ["Link", "Unlink"]) if action == "Link": tag_id = st.text_input("Tag ID") matric_no = st.text_input("Matric No (for student, optional)") username = st.text_input("Username (for user, optional)") if st.button("Link Tag"): if not matric_no and not username: st.error("Provide either Matric No or Username") else: data = {"tag_id": tag_id} if matric_no: data["matric_no"] = matric_no if username: data["username"] = username response = api_call('POST', '/admin/tags/link', data=data) if response.status_code == 200: st.success("Tag linked!") st.json(response.json()) else: st.error(f"Failed to link tag: {response.text}") elif action == "Unlink": tag_id = st.text_input("Tag ID") if st.button("Unlink Tag"): response = api_call('DELETE', f'/admin/tags/unlink/{tag_id}') if response.status_code == 200: st.success("Tag unlinked!") st.json(response.json()) else: st.error(f"Failed to unlink tag: {response.text}") elif page == "Devices": st.header("Device Management") action = st.selectbox("Action", ["List", "Create", "Delete"]) if action == "List": if st.button("Get Devices"): response = api_call('GET', '/admin/devices/') if response.status_code == 200: devices = response.json() st.json(devices) else: st.error(f"Failed to fetch devices: {response.text}") elif action == "Create": device_name = st.text_input("Device Name") location = st.text_input("Location") department = st.selectbox("Department", ["Computer Science", "Engineering", "Business Administration", "Law", "Medicine"]) if st.button("Create Device"): data = { "device_name": device_name, "location": location, "department": department } response = api_call('POST', '/admin/devices/', data=data) if response.status_code == 201: st.success("Device created!") st.json(response.json()) else: st.error(f"Failed to create device: {response.text}") elif action == "Delete": device_id = st.number_input("Device ID", min_value=1) if st.button("Delete Device"): response = api_call('DELETE', f'/admin/devices/{device_id}') if response.status_code == 200: st.success("Device deleted!") st.json(response.json()) else: st.error(f"Failed to delete device: {response.text}") elif page == "Clearance": st.header("Clearance Management") matric_no = st.text_input("Matric No") department = st.selectbox("Department", ["Library", "Student Affairs", "Bursary", "Academic Affairs", "Health Center"]) status = st.selectbox("Status", ["pending", "approved", "rejected"]) remarks = st.text_area("Remarks (optional)") if st.button("Update Clearance"): data = { "matric_no": matric_no, "department": department, "status": status, "remarks": remarks if remarks else None } response = api_call('PUT', '/clearance/update', data=data) if response.status_code == 200: st.success("Clearance updated!") st.json(response.json()) else: st.error(f"Failed to update clearance: {response.text}") elif page == "RFID": st.header("RFID Check Status") tag_id = st.text_input("Tag ID") if st.button("Check Status"): data = {"tag_id": tag_id} headers = {'x-api-key': 'some_api_key_if_needed'} # If required, but backend uses Security response = api_call('POST', '/rfid/check-status', data=data, headers=headers) if response.status_code == 200: st.json(response.json()) else: st.error(f"Failed to check status: {response.text}") elif page == "Scanners": st.header("Scanner Management") action = st.selectbox("Action", ["Activate", "Retrieve"]) if action == "Activate": api_key = st.text_input("Device API Key") if st.button("Activate Scanner"): data = {"api_key": api_key} response = api_call('POST', '/rfid/scanners/activate', data=data) if response.status_code == 204: st.success("Scanner activated!") else: st.error(f"Failed to activate: {response.text}") elif action == "Retrieve": if st.button("Retrieve Tag"): response = api_call('GET', '/rfid/scanners/retrieve') if response.status_code == 200: st.json(response.json()) else: st.error(f"No tag scanned yet: {response.text}") elif page == "Profile": st.header("My Profile") if st.button("Get My Profile"): response = api_call('GET', '/users/me') if response.status_code == 200: st.json(response.json()) else: st.error(f"Failed to fetch profile: {response.text}")