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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +189 -201
app.py CHANGED
@@ -2,13 +2,13 @@ import streamlit as st
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 v2.0"
12
  }
13
  )
14
 
@@ -31,72 +31,15 @@ st.markdown("""
31
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
32
  }
33
 
34
- /* Enhanced Sidebar */
35
- [data-testid="stSidebar"] {
36
- background: linear-gradient(145deg, #1a1a1a, #2d2d2d) !important;
37
- }
38
-
39
- .st-emotion-cache-1dj0hjr {
40
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
41
- border-radius: 10px;
42
- padding: 12px 18px;
43
- margin: 8px 0;
44
- }
45
-
46
- .st-emotion-cache-1dj0hjr:hover {
47
- transform: translateX(12px);
48
- background: rgba(255,255,255,0.15) !important;
49
- }
50
-
51
- /* Modern Table Design */
52
- .dataframe {
53
- border-radius: 12px;
54
- overflow: hidden;
55
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
56
- }
57
-
58
- .dataframe th {
59
- background: #2c3e50 !important;
60
- color: white !important;
61
- font-weight: 600 !important;
62
- }
63
-
64
- /* Status Badges */
65
- .status-badge {
66
- padding: 6px 14px;
67
- border-radius: 20px;
68
- font-weight: 500;
69
- display: inline-flex;
70
- align-items: center;
71
- gap: 8px;
72
- }
73
-
74
- .pending { background: #fff3cd; color: #856404; }
75
- .in-progress { background: #cce5ff; color: #004085; }
76
- .completed { background: #d4edda; color: #155724; }
77
-
78
- /* Delete Button Style */
79
- .delete-btn {
80
- background: #ff4444 !important;
81
- color: white !important;
82
- border-radius: 20px;
83
- padding: 4px 12px;
84
- font-size: 0.9em;
85
- }
86
-
87
- /* Progress Bars */
88
- .progress-container {
89
- background: #f0f0f0;
90
- border-radius: 10px;
91
- height: 10px;
92
- overflow: hidden;
93
  }
94
 
95
- .progress-bar {
96
- height: 100%;
97
- background: #3498db;
98
- transition: width 0.3s ease;
99
- }
100
  </style>
101
  """, unsafe_allow_html=True)
102
 
@@ -226,35 +169,47 @@ def main():
226
  except Exception as e:
227
  st.error(f"❌ Delete failed: {str(e)}")
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  # Sidebar Navigation
230
- menu_items = ["🏠 Dashboard", "πŸ“₯ Task Entry", "πŸ‘€ Task Explorer", "βš™οΈ Settings"]
231
  if st.session_state.is_admin:
232
  menu_items.insert(3, "πŸ—οΈ Project Management")
233
 
234
  with st.sidebar:
235
  st.title("πŸ” Navigation")
236
  menu = st.radio("", menu_items, label_visibility="collapsed")
237
-
238
- # Progress Overview
239
- if menu == "🏠 Dashboard":
240
- st.markdown("---")
241
- tasks = get_tasks()
242
- if tasks:
243
- completed = len([t for t in tasks if t['status'] == "Completed"])
244
- progress = (completed / len(tasks)) * 100
245
- st.markdown(f"""
246
- <div style="margin: 1rem 0;">
247
- <div style="display: flex; justify-content: space-between;">
248
- <span>πŸ“ˆ Progress</span>
249
- <span>{progress:.0f}%</span>
250
- </div>
251
- <div class="progress-container">
252
- <div class="progress-bar" style="width: {progress}%"></div>
253
- </div>
254
- </div>
255
- """, unsafe_allow_html=True)
256
 
257
- # Dashboard View
258
  if menu == "🏠 Dashboard":
259
  tasks = get_tasks()
260
  if tasks:
@@ -267,179 +222,212 @@ def main():
267
  m3.metric("⏳ In Progress", len(df[df['status'] == "In Progress"]))
268
  m4.metric("πŸ“­ Pending", len(df[df['status'] == "Pending"]))
269
 
270
- # Visualizations
271
- col1, col2 = st.columns(2)
272
- with col1:
273
- with st.container(border=True):
274
- st.subheader("πŸ“Š Status Distribution")
275
- fig = px.pie(df, names='status', hole=0.4,
276
- color_discrete_sequence=px.colors.qualitative.Pastel1)
277
- st.plotly_chart(fig, use_container_width=True)
278
-
279
- with col2:
280
- with st.container(border=True):
281
- st.subheader("πŸ“… Project Timeline")
282
- timeline_df = df.copy()
283
- timeline_df['date'] = pd.to_datetime(timeline_df['date'])
284
- fig = px.timeline(timeline_df, x_start="date", x_end="date", y="project",
285
- color="status", color_discrete_map={
286
- "Pending": "#FFD700",
287
- "In Progress": "#87CEEB",
288
- "Completed": "#90EE90"
289
- })
290
- st.plotly_chart(fig, use_container_width=True)
291
  else:
292
  st.info("πŸ“­ No tasks found. Start by adding new tasks!")
293
 
294
- # Task Entry
295
- elif menu == "πŸ“₯ Task Entry":
 
 
 
 
 
 
 
 
 
296
  with st.form("task_form", clear_on_submit=True):
297
- st.subheader("βž• Add New Task")
298
- col1, col2 = st.columns(2)
 
 
 
 
 
 
 
 
 
 
299
 
 
300
  with col1:
301
- task = st.text_area("πŸ“ Task Description", height=100)
302
- task_type = st.selectbox("πŸ“¦ Task Type",
303
- ["Design", "Procurement", "Construction", "Testing", "Other"])
304
-
305
  with col2:
306
- projects_ref = db.collection("projects")
307
- projects = [proj.id for proj in projects_ref.stream()] + ["Add New Project"]
308
- selected_project = st.selectbox("πŸ—οΈ Project", projects)
309
- if selected_project == "Add New Project":
310
- selected_project = st.text_input("✨ New Project Name")
311
-
312
- status = st.selectbox("πŸ“Œ Status",
313
- ["Pending", "In Progress", "Completed"])
314
- date = st.date_input("πŸ“… Due Date", min_value=datetime.today())
315
 
316
- if st.form_submit_button("πŸ’Ύ Save Task"):
317
- if task and selected_project:
318
- try:
319
- db.collection("tasks").add({
320
- "user": st.session_state.email,
321
- "task": task,
322
- "type": task_type,
323
- "project": selected_project,
324
- "status": status,
325
- "date": str(date)
326
- })
327
- st.success("βœ… Task saved successfully!")
328
- st.rerun()
329
- except Exception as e:
330
- st.error(f"❌ Error: {str(e)}")
331
 
332
- # Task Explorer with Delete
333
- elif menu == "πŸ‘€ Task Explorer":
 
334
  tasks = get_tasks()
 
335
  if tasks:
336
  df = pd.DataFrame(tasks)
337
-
338
- # Filters
339
  col1, col2, col3 = st.columns(3)
340
  with col1:
341
- status_filter = st.multiselect("πŸ“Œ Filter by Status",
342
- df['status'].unique(), df['status'].unique())
343
  with col2:
344
- project_filter = st.multiselect("πŸ—οΈ Filter by Project",
345
- df['project'].unique())
346
  with col3:
347
- date_filter = st.date_input("πŸ“… Filter by Date")
348
 
349
- # Apply filters
350
- filtered_df = df[
351
- (df['status'].isin(status_filter)) &
352
- (df['project'].isin(project_filter if project_filter else df['project'].unique())) &
353
- (df['date'] == (str(date_filter) if date_filter else df['date']))
354
- ]
 
355
 
356
- # Display Table with Delete
357
  if not filtered_df.empty:
358
- for _, row in filtered_df.iterrows():
359
- col1, col2 = st.columns([5,1])
360
- with col1:
361
- st.markdown(f"""
362
- <div style="padding: 1rem; margin: 0.5rem 0; border-radius: 10px;
363
- background: {'#f0f0f0' if _%2==0 else 'white'}">
364
- <b>{row['task']}</b><br>
365
- <span class="status-badge {row['status'].lower().replace(' ', '-')}">
366
- {row['status']}
367
- </span>
368
- <span style="margin-left: 1rem;">πŸ“… {row['date']}</span>
369
- </div>
370
- """, unsafe_allow_html=True)
371
- with col2:
372
- if st.button("πŸ—‘οΈ", key=f"del_{row['id']}"):
373
- delete_task(row['id'])
374
- st.markdown(f"πŸ“„ Showing {len(filtered_df)} of {len(df)} tasks")
375
  else:
376
- st.info("πŸ” No tasks match the filters")
377
  else:
378
- st.info("πŸ“­ No tasks found. Start by adding new tasks!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
 
380
- # Admin Project Management
381
- elif menu == "πŸ—οΈ Project Management" and st.session_state.is_admin:
382
- st.subheader("πŸ—οΈ Project Management")
383
  try:
384
  projects_ref = db.collection("projects")
385
  projects = [proj.id for proj in projects_ref.stream()]
386
  except Exception as e:
387
- st.error(f"❌ Error loading projects: {str(e)}")
388
  projects = []
389
 
390
  if projects:
391
- st.subheader("πŸ“‹ Existing Projects")
392
  for project in projects:
393
- col1, col2 = st.columns([3,1])
394
  with col1:
395
- st.markdown(f"🏒 **{project}**")
396
  with col2:
397
- if st.button(f"πŸ—‘οΈ Delete {project}", key=f"del_{project}"):
398
  try:
399
  db.collection("projects").document(project).delete()
400
  st.rerun()
401
  except Exception as e:
402
- st.error(f"❌ Delete failed: {str(e)}")
403
 
404
- st.subheader("βž• Add New Project")
405
  with st.form("project_form"):
406
- new_project = st.text_input("✨ New Project Name")
407
- if st.form_submit_button("πŸ’Ύ Create Project"):
408
  if new_project:
409
  try:
410
  db.collection("projects").document(new_project).set({
411
  "created_by": st.session_state.email,
412
  "created_at": datetime.now().strftime("%Y-%m-%d")
413
  })
414
- st.success("βœ… Project created successfully!")
415
  st.rerun()
416
  except Exception as e:
417
- st.error(f"❌ Error: {str(e)}")
418
 
419
- # Settings
420
- elif menu == "βš™οΈ Settings":
421
- st.subheader("βš™οΈ Account Settings")
422
  with st.form("password_change"):
423
- st.write("### πŸ”’ Change Password")
424
- old_password = st.text_input("πŸ”‘ Current Password", type="password")
425
- new_password = st.text_input("πŸ†• New Password", type="password")
426
- confirm_password = st.text_input("βœ… Confirm New Password", type="password")
427
 
428
- if st.form_submit_button("πŸ”„ Update Password"):
429
  if new_password == confirm_password:
430
  try:
431
  auth.update_user(
432
  st.session_state.user_uid,
433
  password=new_password
434
  )
435
- st.success("πŸ”‘ Password updated successfully!")
436
  except Exception as e:
437
- st.error(f"❌ Error: {str(e)}")
438
  else:
439
- st.error("πŸ”’ Passwords do not match!")
440
 
441
  st.markdown("---")
442
- if st.button("πŸšͺ Logout", type="primary"):
443
  st.session_state.authenticated = False
444
  st.rerun()
445
 
 
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
 
 
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
 
 
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")
207
 
208
  with st.sidebar:
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:
 
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