arif670 commited on
Commit
ccf8aa1
Β·
verified Β·
1 Parent(s): 46762be

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -235
app.py CHANGED
@@ -2,17 +2,17 @@ import streamlit as st
2
 
3
  # Configure page first
4
  st.set_page_config(
5
- page_title="TODO LIST FOR DAILY TASK MANAGEMENT AND MONITORING",
6
  layout="wide",
7
  page_icon="πŸ“‹",
8
  menu_items={
9
  'Get Help': 'https://github.com',
10
  'Report a bug': "https://github.com",
11
- 'About': "# Task Management System v3.0"
12
  }
13
  )
14
 
15
- # Enhanced UI CSS
16
  st.markdown("""
17
  <style>
18
  /* Modern UI Enhancements */
@@ -31,32 +31,46 @@ st.markdown("""
31
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
32
  }
33
 
34
- /* Popup Styling */
35
- .popup {
36
- border-radius: 15px;
37
- padding: 1.5rem;
38
- margin: 1rem 0;
39
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
 
42
- /* Other styles remain same from previous version */
 
 
 
 
43
  </style>
44
  """, unsafe_allow_html=True)
45
 
46
- import firebase_admin
47
- from firebase_admin import credentials, firestore, auth, exceptions
48
- import pandas as pd
49
- import plotly.express as px
50
- from datetime import datetime, timedelta
51
-
52
- # Initialize Firebase
53
- if not firebase_admin._apps:
54
- cred = credentials.Certificate("firebase_credentials.json")
55
- firebase_admin.initialize_app(cred)
56
- db = firestore.client()
57
 
58
- # -------------------- Admin Setup --------------------
59
- def create_default_admin():
60
  try:
61
  admin_email = "[email protected]"
62
  try:
@@ -68,39 +82,16 @@ def create_default_admin():
68
  display_name="Admin"
69
  )
70
  auth.set_custom_user_claims(admin_user.uid, {'admin': True})
71
- db.collection("users").document(admin_user.uid).set({
72
- "email": admin_email,
73
- "is_admin": True,
74
- "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
75
- })
76
  except Exception as e:
77
- print(f"Admin setup error: {str(e)}")
78
 
79
- create_default_admin()
80
-
81
- # -------------------- Authentication --------------------
82
- def register_user(email, password):
83
- try:
84
- user = auth.create_user(email=email, password=password)
85
- db.collection("users").document(user.uid).set({
86
- "email": email,
87
- "is_admin": False,
88
- "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
89
- })
90
- st.success("πŸŽ‰ Registration successful! Please sign in.")
91
- except Exception as e:
92
- st.error(f"⚠️ Error: {e}")
93
-
94
- def authenticate_user(email):
95
- try:
96
- return auth.get_user_by_email(email)
97
- except Exception as e:
98
- st.error(f"πŸ” Authentication error: {str(e)}")
99
- return None
100
-
101
- # -------------------- Main App --------------------
102
  def main():
103
- # Session State Initialization
 
 
 
 
104
  if "authenticated" not in st.session_state:
105
  st.session_state.update({
106
  "authenticated": False,
@@ -114,37 +105,45 @@ def main():
114
  if not st.session_state.authenticated:
115
  st.markdown("<div class='header'><h1>πŸ“‹ To-Do List Management System</h1><h3>Daily Task Monitoring & Productivity Tracking</h3></div>", unsafe_allow_html=True)
116
 
117
- auth_col1, auth_col2 = st.columns(2)
118
- with auth_col1:
119
  with st.expander("πŸ”‘ Sign In", expanded=True):
120
  with st.form("signin_form"):
121
  email = st.text_input("πŸ“§ Email")
122
  password = st.text_input("πŸ”’ Password", type="password")
123
  if st.form_submit_button("πŸš€ Login"):
124
- user = authenticate_user(email)
125
- if user:
126
- custom_claims = user.custom_claims or {}
127
  user_doc = db.collection("users").document(user.uid).get().to_dict()
128
  st.session_state.update({
129
  "authenticated": True,
130
  "email": user.email,
131
  "user_uid": user.uid,
132
- "is_admin": custom_claims.get('admin', False) or user_doc.get('is_admin', False)
133
  })
134
  st.rerun()
 
 
135
 
136
- with auth_col2:
137
  with st.expander("πŸ“ Sign Up", expanded=True):
138
  with st.form("signup_form"):
139
  new_email = st.text_input("πŸ“¨ New Email")
140
  new_password = st.text_input("πŸ” New Password", type="password")
141
  if st.form_submit_button("🌟 Register"):
142
- if new_email and new_password:
143
- register_user(new_email, new_password)
 
 
 
 
 
 
 
 
144
  return
145
 
146
- # -------------------- Authenticated User Flow --------------------
147
- # Custom Header
148
  st.markdown(f"""
149
  <div class='header'>
150
  <h1>πŸ“‹ To-Do List Management System</h1>
@@ -152,11 +151,11 @@ def main():
152
  </div>
153
  """, unsafe_allow_html=True)
154
 
155
- # Task Management Functions
156
  def get_tasks():
157
  try:
158
- tasks_ref = db.collection("tasks").where("user", "==", st.session_state.email)
159
- return [{"id": task.id, **task.to_dict()} for task in tasks_ref.stream()]
160
  except Exception as e:
161
  st.error(f"πŸ“¦ Error loading tasks: {str(e)}")
162
  return []
@@ -169,38 +168,35 @@ def main():
169
  except Exception as e:
170
  st.error(f"❌ Delete failed: {str(e)}")
171
 
172
- # Popup Reminders
173
- def show_reminders():
174
- tasks = get_tasks()
175
- overdue = []
176
- due_soon = []
177
-
178
- for task in tasks:
179
- if task['status'] != "Completed":
180
- task_date = datetime.strptime(task['date'], "%Y-%m-%d").date()
181
- delta = (task_date - datetime.today().date()).days
182
- if delta < 0:
183
- overdue.append(task)
184
- elif 0 <= delta <= 3:
185
- due_soon.append(task)
186
-
187
- if overdue or due_soon:
188
- with st.expander("πŸ”” Task Reminders", expanded=True):
189
- if overdue:
190
- st.error("##### ⚠️ Overdue Tasks")
191
- for task in overdue:
192
- st.markdown(f"**{task['task']}** ({task['project']}) - Due {task['date']}")
193
- if due_soon:
194
- st.warning("##### ⏳ Upcoming Deadlines")
195
- for task in due_soon:
196
- st.markdown(f"**{task['task']}** ({task['project']}) - Due {task['date']}")
197
-
198
- # Show reminders on first login
199
  if st.session_state.first_login:
200
- show_reminders()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  st.session_state.first_login = False
202
 
203
- # Sidebar Navigation
204
  menu_items = ["🏠 Dashboard", "πŸ“₯ Task Entry", "πŸ‘€ Task Explorer", "✏️ Edit Tasks", "βš™οΈ Settings"]
205
  if st.session_state.is_admin:
206
  menu_items.insert(3, "πŸ—οΈ Project Management")
@@ -209,225 +205,188 @@ def main():
209
  st.title("πŸ” Navigation")
210
  menu = st.radio("", menu_items, label_visibility="collapsed")
211
 
212
- # Dashboard View (Simplified without timeline)
213
  if menu == "🏠 Dashboard":
214
  tasks = get_tasks()
215
  if tasks:
216
  df = pd.DataFrame(tasks)
217
 
218
- # Metrics
219
- m1, m2, m3, m4 = st.columns(4)
220
- m1.metric("πŸ“Œ Total Tasks", len(df))
221
- m2.metric("βœ… Completed", len(df[df['status'] == "Completed"]))
222
- m3.metric("⏳ In Progress", len(df[df['status'] == "In Progress"]))
223
- m4.metric("πŸ“­ Pending", len(df[df['status'] == "Pending"]))
224
 
225
- # Single Visualization
226
  with st.container(border=True):
227
  st.subheader("πŸ“Š Task Status Distribution")
228
  fig = px.pie(df, names='status', hole=0.4,
229
- color_discrete_sequence=px.colors.qualitative.Pastel1,
230
- width=800, height=400)
231
  st.plotly_chart(fig, use_container_width=True)
232
  else:
233
  st.info("πŸ“­ No tasks found. Start by adding new tasks!")
234
 
235
- # Task Entry (Remains same from previous version)
236
- elif menu == "πŸ“ Task Entry":
237
- st.title("πŸ“ Add New Task")
238
- try:
239
- projects_ref = db.collection("projects")
240
- projects = [proj.id for proj in projects_ref.stream()]
241
- projects.append("Add New Project")
242
- except Exception as e:
243
- st.error(f"Error loading projects: {str(e)}")
244
- projects = ["Add New Project"]
245
-
246
  with st.form("task_form", clear_on_submit=True):
247
- task = st.text_input("Task Description", help="Enter detailed task description")
248
- task_type = st.selectbox("Task Type", ["Design", "Procurement", "Construction", "Testing", "Other"])
249
- selected_project = st.selectbox("Project", projects)
250
-
251
- if selected_project == "Add New Project":
252
- new_project = st.text_input("New Project Name")
253
- if new_project:
254
- try:
255
- db.collection("projects").document(new_project).set({"created_by": st.session_state.email})
256
- selected_project = new_project
257
- except Exception as e:
258
- st.error(f"Error creating project: {str(e)}")
259
-
260
  col1, col2 = st.columns(2)
 
261
  with col1:
262
- status = st.selectbox("Status", ["Pending", "In Progress", "Completed"])
 
 
 
263
  with col2:
264
- date = st.date_input("Target Date", min_value=datetime.today())
 
 
 
 
 
 
265
 
266
- if st.form_submit_button("Add Task"):
267
  try:
268
  db.collection("tasks").add({
269
  "user": st.session_state.email,
270
  "task": task,
271
  "type": task_type,
272
- "project": selected_project,
273
  "status": status,
274
  "date": str(date)
275
  })
276
- st.success("Task added successfully!")
277
  st.rerun()
278
  except Exception as e:
279
- st.error(f"Error saving task: {str(e)}")
280
 
281
- # Task Explorer with Delete (Remains same from previous version)
282
- elif menu == "πŸ‘€ View Tasks":
283
- st.title("πŸ” Task Explorer")
284
  tasks = get_tasks()
285
-
286
  if tasks:
287
  df = pd.DataFrame(tasks)
 
288
  col1, col2, col3 = st.columns(3)
289
  with col1:
290
- status_filter = st.multiselect("Status", df['status'].unique(), df['status'].unique())
291
  with col2:
292
- project_filter = st.multiselect("Project", df['project'].unique())
293
  with col3:
294
- date_filter = st.date_input("Filter by Date")
295
 
296
- filtered_df = df.copy()
297
- if status_filter:
298
- filtered_df = filtered_df[filtered_df['status'].isin(status_filter)]
299
- if project_filter:
300
- filtered_df = filtered_df[filtered_df['project'].isin(project_filter)]
301
- if date_filter:
302
- filtered_df = filtered_df[filtered_df['date'] == str(date_filter)]
303
 
304
  if not filtered_df.empty:
305
- styled_df = filtered_df[['task', 'project', 'status', 'date']].copy()
306
- styled_df['status'] = styled_df['status'].apply(
307
- lambda x: f'<span class="status-badge {x.lower().replace(" ", "-")}">{x}</span>'
308
- )
309
- st.markdown(styled_df.style.hide(axis="index")
310
- .set_table_styles([
311
- {'selector': 'th', 'props': 'background-color: #2c3e50; color: white;'},
312
- {'selector': 'td', 'props': 'padding: 12px; border-bottom: 1px solid #ddd;'}
313
- ]).to_html(), unsafe_allow_html=True)
 
 
 
 
 
 
 
314
  else:
315
- st.info("No tasks match the filters")
316
  else:
317
- st.info("No tasks found. Start by adding new tasks!")
318
 
319
- # Edit Tasks (New Enhanced Version)
320
  elif menu == "✏️ Edit Tasks":
321
- st.subheader("✏️ Edit Task")
322
  tasks = get_tasks()
323
-
324
  if tasks:
325
- task_options = [f"{task['task']} ({task['project']} - {task['date']})" for task in tasks]
326
- selected_task = st.selectbox("Select Task to Edit", task_options)
327
- task_id = next(task['id'] for task in tasks if f"{task['task']} ({task['project']} - {task['date']})" == selected_task)
328
- task_to_edit = next(task for task in tasks if task['id'] == task_id)
329
 
330
  with st.form("edit_form"):
331
  col1, col2 = st.columns(2)
332
  with col1:
333
- new_task = st.text_area("Task Description", value=task_to_edit['task'], height=100)
334
- new_type = st.selectbox("Task Type",
335
  ["Design", "Procurement", "Construction", "Testing", "Other"],
336
- index=["Design", "Procurement", "Construction", "Testing", "Other"].index(task_to_edit['type']))
337
-
338
  with col2:
339
- projects_ref = db.collection("projects")
340
- projects = [proj.id for proj in projects_ref.stream()] + ["Add New Project"]
341
- new_project = st.selectbox("Project", projects, index=projects.index(task_to_edit['project']) if task_to_edit['project'] in projects else 0)
342
  if new_project == "Add New Project":
343
  new_project = st.text_input("New Project Name")
344
-
345
- new_status = st.selectbox("Status",
346
- ["Pending", "In Progress", "Completed"],
347
- index=["Pending", "In Progress", "Completed"].index(task_to_edit['status']))
348
- new_date = st.date_input("Due Date",
349
- value=datetime.strptime(task_to_edit['date'], "%Y-%m-%d"))
350
 
351
  if st.form_submit_button("πŸ’Ύ Save Changes"):
352
  try:
353
- update_data = {
354
  "task": new_task,
355
  "type": new_type,
356
- "status": new_status,
357
  "project": new_project,
 
358
  "date": str(new_date)
359
- }
360
- db.collection("tasks").document(task_id).update(update_data)
361
- st.success("βœ… Task updated successfully!")
362
  st.rerun()
363
  except Exception as e:
364
  st.error(f"❌ Update failed: {str(e)}")
365
  else:
366
- st.info("πŸ“­ No tasks available for editing")
367
 
368
- # Project Management (Admin Only - Remains same from previous version)
369
- elif menu == "πŸ—οΈ Projects":
370
- st.title("πŸ—οΈ Project Management")
371
- try:
372
- projects_ref = db.collection("projects")
373
- projects = [proj.id for proj in projects_ref.stream()]
374
- except Exception as e:
375
- st.error(f"Error loading projects: {str(e)}")
376
- projects = []
377
 
378
  if projects:
379
- st.subheader("Existing Projects")
380
  for project in projects:
381
- col1, col2 = st.columns([3, 1])
382
  with col1:
383
- st.markdown(f"**{project}**")
384
  with col2:
385
- if st.button(f"Delete {project}", key=f"del_{project}"):
386
- try:
387
- db.collection("projects").document(project).delete()
388
- st.rerun()
389
- except Exception as e:
390
- st.error(f"Error deleting project: {str(e)}")
391
 
392
- st.subheader("Add New Project")
393
  with st.form("project_form"):
 
394
  new_project = st.text_input("Project Name")
395
- if st.form_submit_button("Create Project"):
396
  if new_project:
397
- try:
398
- db.collection("projects").document(new_project).set({
399
- "created_by": st.session_state.email,
400
- "created_at": datetime.now().strftime("%Y-%m-%d")
401
- })
402
- st.success("Project created successfully!")
403
- st.rerun()
404
- except Exception as e:
405
- st.error(f"Error creating project: {str(e)}")
406
 
407
- # Settings (Remains same from previous version)
408
- elif menu == "βš™οΈ Settings":
409
- st.title("βš™οΈ Account Settings")
410
- with st.form("password_change"):
411
- st.subheader("Change Password")
412
- old_password = st.text_input("Current Password", type="password")
413
- new_password = st.text_input("New Password", type="password")
414
- confirm_password = st.text_input("Confirm New Password", type="password")
415
 
416
- if st.form_submit_button("Update Password"):
417
- if new_password == confirm_password:
418
  try:
419
- auth.update_user(
420
- st.session_state.user_uid,
421
- password=new_password
422
- )
423
- st.success("Password updated successfully!")
424
  except Exception as e:
425
- st.error(f"Password update failed: {str(e)}")
426
  else:
427
- st.error("New passwords do not match")
428
 
429
- st.markdown("---")
430
- if st.button("Logout", type="primary"):
431
  st.session_state.authenticated = False
432
  st.rerun()
433
 
 
2
 
3
  # Configure page first
4
  st.set_page_config(
5
+ page_title="To-DO-LIST FOR DAILY TASK MANAGEMENT AND MONITORING",
6
  layout="wide",
7
  page_icon="πŸ“‹",
8
  menu_items={
9
  'Get Help': 'https://github.com',
10
  'Report a bug': "https://github.com",
11
+ 'About': "# Task Management System v3.2"
12
  }
13
  )
14
 
15
+ # Custom CSS for enhanced UI
16
  st.markdown("""
17
  <style>
18
  /* Modern UI Enhancements */
 
31
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
32
  }
33
 
34
+ /* Status Badges */
35
+ .status-badge {
36
+ padding: 6px 14px;
37
+ border-radius: 20px;
38
+ font-weight: 500;
39
+ display: inline-flex;
40
+ align-items: center;
41
+ gap: 8px;
42
+ }
43
+
44
+ .pending { background: #fff3cd; color: #856404; }
45
+ .in-progress { background: #cce5ff; color: #004085; }
46
+ .completed { background: #d4edda; color: #155724; }
47
+
48
+ /* Progress Bars */
49
+ .progress-container {
50
+ background: #f0f0f0;
51
+ border-radius: 10px;
52
+ height: 10px;
53
+ overflow: hidden;
54
  }
55
 
56
+ .progress-bar {
57
+ height: 100%;
58
+ background: #3498db;
59
+ transition: width 0.3s ease;
60
+ }
61
  </style>
62
  """, unsafe_allow_html=True)
63
 
64
+ def initialize_firebase():
65
+ import firebase_admin
66
+ from firebase_admin import credentials, firestore, auth
67
+
68
+ if not firebase_admin._apps:
69
+ cred = credentials.Certificate("firebase_credentials.json")
70
+ firebase_admin.initialize_app(cred)
71
+ return firestore.client(), auth
 
 
 
72
 
73
+ def create_default_admin(auth):
 
74
  try:
75
  admin_email = "[email protected]"
76
  try:
 
82
  display_name="Admin"
83
  )
84
  auth.set_custom_user_claims(admin_user.uid, {'admin': True})
85
+ return admin_user
 
 
 
 
86
  except Exception as e:
87
+ st.error(f"Admin setup error: {str(e)}")
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  def main():
90
+ # Initialize Firebase within Streamlit context
91
+ db, auth = initialize_firebase()
92
+ create_default_admin(auth)
93
+
94
+ # Session State Management
95
  if "authenticated" not in st.session_state:
96
  st.session_state.update({
97
  "authenticated": False,
 
105
  if not st.session_state.authenticated:
106
  st.markdown("<div class='header'><h1>πŸ“‹ To-Do List Management System</h1><h3>Daily Task Monitoring & Productivity Tracking</h3></div>", unsafe_allow_html=True)
107
 
108
+ col1, col2 = st.columns(2)
109
+ with col1:
110
  with st.expander("πŸ”‘ Sign In", expanded=True):
111
  with st.form("signin_form"):
112
  email = st.text_input("πŸ“§ Email")
113
  password = st.text_input("πŸ”’ Password", type="password")
114
  if st.form_submit_button("πŸš€ Login"):
115
+ try:
116
+ user = auth.get_user_by_email(email)
 
117
  user_doc = db.collection("users").document(user.uid).get().to_dict()
118
  st.session_state.update({
119
  "authenticated": True,
120
  "email": user.email,
121
  "user_uid": user.uid,
122
+ "is_admin": user.custom_claims.get('admin', False) if user.custom_claims else user_doc.get('is_admin', False)
123
  })
124
  st.rerun()
125
+ except Exception as e:
126
+ st.error(f"πŸ” Authentication failed: {str(e)}")
127
 
128
+ with col2:
129
  with st.expander("πŸ“ Sign Up", expanded=True):
130
  with st.form("signup_form"):
131
  new_email = st.text_input("πŸ“¨ New Email")
132
  new_password = st.text_input("πŸ” New Password", type="password")
133
  if st.form_submit_button("🌟 Register"):
134
+ try:
135
+ user = auth.create_user(email=new_email, password=new_password)
136
+ db.collection("users").document(user.uid).set({
137
+ "email": new_email,
138
+ "is_admin": False,
139
+ "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
140
+ })
141
+ st.success("πŸŽ‰ Registration successful! Please sign in.")
142
+ except Exception as e:
143
+ st.error(f"⚠️ Registration failed: {str(e)}")
144
  return
145
 
146
+ # Authenticated User Flow
 
147
  st.markdown(f"""
148
  <div class='header'>
149
  <h1>πŸ“‹ To-Do List Management System</h1>
 
151
  </div>
152
  """, unsafe_allow_html=True)
153
 
154
+ # Core Functions
155
  def get_tasks():
156
  try:
157
+ tasks = db.collection("tasks").where("user", "==", st.session_state.email).stream()
158
+ return [{"id": task.id, **task.to_dict()} for task in tasks]
159
  except Exception as e:
160
  st.error(f"πŸ“¦ Error loading tasks: {str(e)}")
161
  return []
 
168
  except Exception as e:
169
  st.error(f"❌ Delete failed: {str(e)}")
170
 
171
+ # Reminders System
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  if st.session_state.first_login:
173
+ with st.expander("πŸ”” Task Reminders", expanded=True):
174
+ tasks = get_tasks()
175
+ overdue = []
176
+ due_soon = []
177
+
178
+ for task in tasks:
179
+ if task['status'] != "Completed":
180
+ task_date = datetime.strptime(task['date'], "%Y-%m-%d").date()
181
+ delta = (task_date - datetime.today().date()).days
182
+ if delta < 0:
183
+ overdue.append(task)
184
+ elif 0 <= delta <= 3:
185
+ due_soon.append(task)
186
+
187
+ if overdue:
188
+ st.error("##### ⚠️ Overdue Tasks")
189
+ for task in overdue:
190
+ st.markdown(f"**{task['task']}** ({task['project']}) - Due {task['date']}")
191
+ if due_soon:
192
+ st.warning("##### ⏳ Upcoming Deadlines")
193
+ for task in due_soon:
194
+ st.markdown(f"**{task['task']}** ({task['project']}) - Due {task['date']}")
195
+ if not overdue and not due_soon:
196
+ st.info("🌟 All tasks are up to date!")
197
  st.session_state.first_login = False
198
 
199
+ # Navigation
200
  menu_items = ["🏠 Dashboard", "πŸ“₯ Task Entry", "πŸ‘€ Task Explorer", "✏️ Edit Tasks", "βš™οΈ Settings"]
201
  if st.session_state.is_admin:
202
  menu_items.insert(3, "πŸ—οΈ Project Management")
 
205
  st.title("πŸ” Navigation")
206
  menu = st.radio("", menu_items, label_visibility="collapsed")
207
 
208
+ # Dashboard View
209
  if menu == "🏠 Dashboard":
210
  tasks = get_tasks()
211
  if tasks:
212
  df = pd.DataFrame(tasks)
213
 
214
+ col1, col2, col3, col4 = st.columns(4)
215
+ col1.metric("πŸ“Œ Total Tasks", len(df))
216
+ col2.metric("βœ… Completed", len(df[df['status'] == "Completed"]))
217
+ col3.metric("⏳ In Progress", len(df[df['status'] == "In Progress"]))
218
+ col4.metric("πŸ“­ Pending", len(df[df['status'] == "Pending"]))
 
219
 
 
220
  with st.container(border=True):
221
  st.subheader("πŸ“Š Task Status Distribution")
222
  fig = px.pie(df, names='status', hole=0.4,
223
+ color_discrete_sequence=px.colors.qualitative.Pastel1)
 
224
  st.plotly_chart(fig, use_container_width=True)
225
  else:
226
  st.info("πŸ“­ No tasks found. Start by adding new tasks!")
227
 
228
+ # Task Entry
229
+ elif menu == "πŸ“₯ Task Entry":
 
 
 
 
 
 
 
 
 
230
  with st.form("task_form", clear_on_submit=True):
231
+ st.subheader("βž• Add New Task")
 
 
 
 
 
 
 
 
 
 
 
 
232
  col1, col2 = st.columns(2)
233
+
234
  with col1:
235
+ task = st.text_area("πŸ“ Task Description", height=100)
236
+ task_type = st.selectbox("πŸ“¦ Task Type",
237
+ ["Design", "Procurement", "Construction", "Testing", "Other"])
238
+
239
  with col2:
240
+ projects = [p.id for p in db.collection("projects").stream()] + ["Add New Project"]
241
+ project = st.selectbox("πŸ—οΈ Project", projects)
242
+ if project == "Add New Project":
243
+ project = st.text_input("✨ New Project Name")
244
+
245
+ status = st.selectbox("πŸ“Œ Status", ["Pending", "In Progress", "Completed"])
246
+ date = st.date_input("πŸ“… Due Date", min_value=datetime.today())
247
 
248
+ if st.form_submit_button("πŸ’Ύ Save Task") and task:
249
  try:
250
  db.collection("tasks").add({
251
  "user": st.session_state.email,
252
  "task": task,
253
  "type": task_type,
254
+ "project": project,
255
  "status": status,
256
  "date": str(date)
257
  })
258
+ st.success("βœ… Task saved successfully!")
259
  st.rerun()
260
  except Exception as e:
261
+ st.error(f"❌ Error: {str(e)}")
262
 
263
+ # Task Explorer
264
+ elif menu == "πŸ‘€ Task Explorer":
 
265
  tasks = get_tasks()
 
266
  if tasks:
267
  df = pd.DataFrame(tasks)
268
+
269
  col1, col2, col3 = st.columns(3)
270
  with col1:
271
+ status_filter = st.multiselect("πŸ“Œ Status", df['status'].unique(), df['status'].unique())
272
  with col2:
273
+ project_filter = st.multiselect("πŸ—οΈ Project", df['project'].unique())
274
  with col3:
275
+ date_filter = st.date_input("πŸ“… Date")
276
 
277
+ filtered_df = df[
278
+ (df['status'].isin(status_filter)) &
279
+ (df['project'].isin(project_filter if project_filter else df['project'].unique())) &
280
+ (df['date'] == (str(date_filter) if date_filter else df['date']))
281
+ ]
 
 
282
 
283
  if not filtered_df.empty:
284
+ for _, row in filtered_df.iterrows():
285
+ col1, col2 = st.columns([5,1])
286
+ with col1:
287
+ st.markdown(f"""
288
+ <div style="padding:1rem; margin:0.5rem 0; border-radius:10px; background:#f8f9fa;">
289
+ <b>{row['task']}</b><br>
290
+ <span class="status-badge {row['status'].lower().replace(' ', '-')}">
291
+ {row['status']}
292
+ </span>
293
+ <span style="margin-left:1rem;">πŸ“… {row['date']}</span>
294
+ </div>
295
+ """, unsafe_allow_html=True)
296
+ with col2:
297
+ if st.button("πŸ—‘οΈ", key=f"del_{row['id']}"):
298
+ delete_task(row['id'])
299
+ st.markdown(f"πŸ“„ Showing {len(filtered_df)} of {len(df)} tasks")
300
  else:
301
+ st.info("πŸ” No tasks match filters")
302
  else:
303
+ st.info("πŸ“­ No tasks found")
304
 
305
+ # Edit Tasks
306
  elif menu == "✏️ Edit Tasks":
 
307
  tasks = get_tasks()
 
308
  if tasks:
309
+ task_options = [f"{t['task']} ({t['project']})" for t in tasks]
310
+ selected = st.selectbox("Select Task", task_options)
311
+ task = next(t for t in tasks if f"{t['task']} ({t['project']})" == selected)
 
312
 
313
  with st.form("edit_form"):
314
  col1, col2 = st.columns(2)
315
  with col1:
316
+ new_task = st.text_area("Description", value=task['task'], height=100)
317
+ new_type = st.selectbox("Type",
318
  ["Design", "Procurement", "Construction", "Testing", "Other"],
319
+ index=["Design", "Procurement", "Construction", "Testing", "Other"].index(task['type']))
 
320
  with col2:
321
+ projects = [p.id for p in db.collection("projects").stream()] + ["Add New Project"]
322
+ new_project = st.selectbox("Project", projects, index=projects.index(task['project']) if task['project'] in projects else 0)
 
323
  if new_project == "Add New Project":
324
  new_project = st.text_input("New Project Name")
325
+ new_status = st.selectbox("Status", ["Pending", "In Progress", "Completed"], index=["Pending", "In Progress", "Completed"].index(task['status']))
326
+ new_date = st.date_input("Due Date", value=datetime.strptime(task['date'], "%Y-%m-%d"))
 
 
 
 
327
 
328
  if st.form_submit_button("πŸ’Ύ Save Changes"):
329
  try:
330
+ db.collection("tasks").document(task['id']).update({
331
  "task": new_task,
332
  "type": new_type,
 
333
  "project": new_project,
334
+ "status": new_status,
335
  "date": str(new_date)
336
+ })
337
+ st.success("βœ… Task updated!")
 
338
  st.rerun()
339
  except Exception as e:
340
  st.error(f"❌ Update failed: {str(e)}")
341
  else:
342
+ st.info("πŸ“­ No tasks to edit")
343
 
344
+ # Project Management (Admin Only)
345
+ elif menu == "πŸ—οΈ Project Management" and st.session_state.is_admin:
346
+ st.subheader("πŸ—οΈ Project Management")
347
+ projects = [p.id for p in db.collection("projects").stream()]
 
 
 
 
 
348
 
349
  if projects:
350
+ st.write("### Existing Projects")
351
  for project in projects:
352
+ col1, col2 = st.columns([4,1])
353
  with col1:
354
+ st.write(f"🏒 {project}")
355
  with col2:
356
+ if st.button(f"πŸ—‘οΈ {project}", key=f"del_{project}"):
357
+ db.collection("projects").document(project).delete()
358
+ st.rerun()
 
 
 
359
 
 
360
  with st.form("project_form"):
361
+ st.write("### Add New Project")
362
  new_project = st.text_input("Project Name")
363
+ if st.form_submit_button("πŸ’Ύ Create Project"):
364
  if new_project:
365
+ db.collection("projects").document(new_project).set({
366
+ "created_by": st.session_state.email,
367
+ "created_at": datetime.now().strftime("%Y-%m-%d")
368
+ })
369
+ st.rerun()
 
 
 
 
370
 
371
+ # Settings
372
+ elif menu == "βš™οΈ Settings":
373
+ with st.form("password_form"):
374
+ st.subheader("πŸ”’ Change Password")
375
+ old_pass = st.text_input("Current Password", type="password")
376
+ new_pass = st.text_input("New Password", type="password")
377
+ confirm_pass = st.text_input("Confirm Password", type="password")
 
378
 
379
+ if st.form_submit_button("πŸ”„ Update Password"):
380
+ if new_pass == confirm_pass:
381
  try:
382
+ auth.update_user(st.session_state.user_uid, password=new_pass)
383
+ st.success("πŸ”‘ Password updated!")
 
 
 
384
  except Exception as e:
385
+ st.error(f"❌ Error: {str(e)}")
386
  else:
387
+ st.error("πŸ”’ Passwords don't match!")
388
 
389
+ if st.button("πŸšͺ Logout"):
 
390
  st.session_state.authenticated = False
391
  st.rerun()
392