Spaces:
Sleeping
Sleeping
| 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}") |