Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +227 -38
src/streamlit_app.py
CHANGED
@@ -1,40 +1,229 @@
|
|
1 |
-
import altair as alt
|
2 |
-
import numpy as np
|
3 |
-
import pandas as pd
|
4 |
import streamlit as st
|
|
|
|
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
st.
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
+
import firebase_admin
|
3 |
+
from firebase_admin import credentials, firestore
|
4 |
|
5 |
+
# Initialize Firebase
|
6 |
+
if not firebase_admin._apps:
|
7 |
+
cred = credentials.Certificate("firebase_key.json")
|
8 |
+
firebase_admin.initialize_app(cred)
|
9 |
+
|
10 |
+
db = firestore.client()
|
11 |
+
|
12 |
+
# -------------------------------
|
13 |
+
# π LOGIN SECTION
|
14 |
+
# -------------------------------
|
15 |
+
def login():
|
16 |
+
st.title("π Login")
|
17 |
+
with st.form("login_form"):
|
18 |
+
username = st.text_input("Username")
|
19 |
+
password = st.text_input("Password", type="password")
|
20 |
+
submitted = st.form_submit_button("Login")
|
21 |
+
if submitted:
|
22 |
+
users_ref = db.collection("users")
|
23 |
+
query = users_ref.where("name", "==", username).where("pass", "==", password).get()
|
24 |
+
if query:
|
25 |
+
user_data = query[0].to_dict()
|
26 |
+
st.session_state.logged_in = True
|
27 |
+
st.session_state.username = username
|
28 |
+
st.session_state.user_role = user_data.get("type", "Standard")
|
29 |
+
st.success(f"Welcome, {username}!")
|
30 |
+
st.rerun()
|
31 |
+
else:
|
32 |
+
st.error("Invalid credentials")
|
33 |
+
|
34 |
+
# -------------------------------
|
35 |
+
# πͺ LOGOUT FUNCTION
|
36 |
+
# -------------------------------
|
37 |
+
def logout():
|
38 |
+
for key in ["logged_in", "username", "user_role", "selected_page", "user_option", "dist_option"]:
|
39 |
+
st.session_state.pop(key, None)
|
40 |
+
st.success("Logged out successfully.")
|
41 |
+
st.rerun()
|
42 |
+
|
43 |
+
# Inject custom CSS
|
44 |
+
st.markdown("""
|
45 |
+
<style>
|
46 |
+
div.stButton > button {
|
47 |
+
width: 100%;
|
48 |
+
height: 45px;
|
49 |
+
font-size: 16px;
|
50 |
+
margin-bottom: 8px;
|
51 |
+
background-color: #31333f;
|
52 |
+
color: white;
|
53 |
+
border: none;
|
54 |
+
border-radius: 6px;
|
55 |
+
}
|
56 |
+
|
57 |
+
div.stButton > button:hover {
|
58 |
+
background-color: #505266;
|
59 |
+
}
|
60 |
+
</style>
|
61 |
+
""", unsafe_allow_html=True)
|
62 |
+
|
63 |
+
# -------------------------------
|
64 |
+
# π§ SIDEBAR NAVIGATION
|
65 |
+
# -------------------------------
|
66 |
+
def show_sidebar():
|
67 |
+
user_role = st.session_state.get("user_role")
|
68 |
+
with st.sidebar:
|
69 |
+
st.markdown(f"**π€ {st.session_state.get('username')} ({user_role})**")
|
70 |
+
st.title("π Navigation")
|
71 |
+
|
72 |
+
# All roles: Home
|
73 |
+
if st.button("π Home"):
|
74 |
+
st.session_state.selected_page = "Home"
|
75 |
+
|
76 |
+
if st.button("π Attendance"):
|
77 |
+
st.session_state.selected_page = "Attendance"
|
78 |
+
|
79 |
+
if st.button("π¦ Order"):
|
80 |
+
st.session_state.selected_page = "Order"
|
81 |
+
|
82 |
+
if st.button("π Logistics"):
|
83 |
+
st.session_state.selected_page = "Logistics"
|
84 |
+
|
85 |
+
if st.button("π οΈ Utility"):
|
86 |
+
st.session_state.selected_page = "Utility"
|
87 |
+
|
88 |
+
# Admin & Standard: Users
|
89 |
+
if user_role in ["Admin", "Back Office"]:
|
90 |
+
if st.button("π Users"):
|
91 |
+
st.session_state.selected_page = "Users"
|
92 |
+
|
93 |
+
# Admin only: Distributors
|
94 |
+
if user_role == "Admin":
|
95 |
+
if st.button("π Distributors"):
|
96 |
+
st.session_state.selected_page = "Distributors"
|
97 |
+
|
98 |
+
if st.button("βΉοΈ About"):
|
99 |
+
st.session_state.selected_page = "About"
|
100 |
+
|
101 |
+
# Logout button
|
102 |
+
if st.button("πͺ Logout"):
|
103 |
+
logout()
|
104 |
+
|
105 |
+
# -------------------------------
|
106 |
+
# π PAGE CONTENT
|
107 |
+
# -------------------------------
|
108 |
+
def home_page():
|
109 |
+
st.title("π Home Page")
|
110 |
+
st.write("Welcome to the homepage.")
|
111 |
+
|
112 |
+
# Users Management with radio options
|
113 |
+
|
114 |
+
def users_page():
|
115 |
+
user_role = st.session_state.get("user_role")
|
116 |
+
if user_role not in ["Admin", "Standard"]:
|
117 |
+
st.error("Access denied.")
|
118 |
+
return
|
119 |
+
|
120 |
+
st.title("π User Management")
|
121 |
+
# Choose form actions
|
122 |
+
options = ["View User"]
|
123 |
+
if user_role in ["Admin", "Standard"]:
|
124 |
+
options.append("Add User")
|
125 |
+
if user_role == "Admin":
|
126 |
+
options.extend(["Delete User", "Update User"])
|
127 |
+
|
128 |
+
user_option = st.radio("Choose action", options, horizontal=True)
|
129 |
+
|
130 |
+
# Add User
|
131 |
+
if user_option == "Add User":
|
132 |
+
st.subheader("Add New User")
|
133 |
+
with st.form("add_user_form"):
|
134 |
+
name = st.text_input("Name")
|
135 |
+
user_type = st.selectbox("Type", ["Admin", "Back Office","Standard", "Guest"])
|
136 |
+
password = st.text_input("Password", type="password")
|
137 |
+
submitted = st.form_submit_button("Submit")
|
138 |
+
if submitted:
|
139 |
+
users_ref = db.collection("users")
|
140 |
+
all_users = users_ref.stream()
|
141 |
+
max_id = 0
|
142 |
+
for doc in all_users:
|
143 |
+
data = doc.to_dict()
|
144 |
+
if isinstance(data.get("id"), int):
|
145 |
+
max_id = max(max_id, data["id"])
|
146 |
+
new_id = max_id + 1
|
147 |
+
users_ref.add({"id": new_id, "name": name, "type": user_type, "pass": password})
|
148 |
+
st.success(f"β
User '{name}' added with ID {new_id}.")
|
149 |
+
|
150 |
+
# View User
|
151 |
+
elif user_option == "View User":
|
152 |
+
st.subheader("π List of Users")
|
153 |
+
try:
|
154 |
+
docs = db.collection("users").get()
|
155 |
+
user_data = [{**doc.to_dict(), "doc_id": doc.id} for doc in docs]
|
156 |
+
if user_data:
|
157 |
+
st.dataframe(user_data)
|
158 |
+
else:
|
159 |
+
st.info("No users found.")
|
160 |
+
except Exception as e:
|
161 |
+
st.error(f"Error fetching users: {e}")
|
162 |
+
|
163 |
+
# Delete User (Admin only)
|
164 |
+
elif user_option == "Delete User":
|
165 |
+
st.subheader("ποΈ Delete User")
|
166 |
+
docs = db.collection("users").get()
|
167 |
+
usernames = [doc.to_dict().get("name") for doc in docs]
|
168 |
+
to_delete = st.selectbox("Select user to delete", usernames)
|
169 |
+
if st.button("Delete"):
|
170 |
+
# find doc
|
171 |
+
for doc in docs:
|
172 |
+
if doc.to_dict().get("name") == to_delete:
|
173 |
+
db.collection("users").document(doc.id).delete()
|
174 |
+
st.success(f"Deleted user {to_delete}.")
|
175 |
+
break
|
176 |
+
|
177 |
+
# Update User (Admin only)
|
178 |
+
elif user_option == "Update User":
|
179 |
+
st.subheader("βοΈ Update User")
|
180 |
+
docs = db.collection("users").get()
|
181 |
+
usernames = [doc.to_dict().get("name") for doc in docs]
|
182 |
+
to_update = st.selectbox("Select user to update", usernames)
|
183 |
+
new_type = st.selectbox("New Type", ["Admin", "Standard", "Guest"])
|
184 |
+
new_pass = st.text_input("New Password", type="password")
|
185 |
+
if st.button("Update"):
|
186 |
+
for doc in docs:
|
187 |
+
if doc.to_dict().get("name") == to_update:
|
188 |
+
update_data = {}
|
189 |
+
if new_type:
|
190 |
+
update_data["type"] = new_type
|
191 |
+
if new_pass:
|
192 |
+
update_data["pass"] = new_pass
|
193 |
+
db.collection("users").document(doc.id).update(update_data)
|
194 |
+
st.success(f"Updated user {to_update}.")
|
195 |
+
break
|
196 |
+
|
197 |
+
# Distributors placeholder
|
198 |
+
|
199 |
+
def distributors_page():
|
200 |
+
if st.session_state.get("user_role") != "Admin":
|
201 |
+
st.error("Access denied.")
|
202 |
+
return
|
203 |
+
st.title("π Distributor Management")
|
204 |
+
st.write("Manage distributors here.")
|
205 |
+
|
206 |
+
# -------------------------------
|
207 |
+
# π MAIN APP
|
208 |
+
# -------------------------------
|
209 |
+
def main():
|
210 |
+
if not st.session_state.get("logged_in"):
|
211 |
+
login()
|
212 |
+
return
|
213 |
+
|
214 |
+
# set default page
|
215 |
+
if "selected_page" not in st.session_state:
|
216 |
+
st.session_state.selected_page = "Home"
|
217 |
+
|
218 |
+
show_sidebar()
|
219 |
+
|
220 |
+
page = st.session_state.selected_page
|
221 |
+
if page == "Home":
|
222 |
+
home_page()
|
223 |
+
elif page == "Users":
|
224 |
+
users_page()
|
225 |
+
elif page == "Distributors":
|
226 |
+
distributors_page()
|
227 |
+
|
228 |
+
if __name__ == "__main__":
|
229 |
+
main()
|