import streamlit as st
from datetime import datetime, date
import utils
import json
# Set page config
st.set_page_config(
page_title="Todo App",
page_icon="✅",
layout="wide",
initial_sidebar_state="expanded"
)
# Initialize session state
if 'todos' not in st.session_state:
st.session_state.todos = []
if 'filter' not in st.session_state:
st.session_state.filter = 'all'
if 'editing_id' not in st.session_state:
st.session_state.editing_id = None
def main():
# Header with link
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
st.markdown("""
""", unsafe_allow_html=True)
# Sidebar for filters and stats
with st.sidebar:
st.header("📊 Statistics")
stats = utils.get_todo_stats(st.session_state.todos)
st.metric("Total Tasks", stats['total'])
st.metric("Completed", stats['completed'])
st.metric("Pending", stats['pending'])
completion_rate = (stats['completed'] / stats['total'] * 100) if stats['total'] > 0 else 0
st.metric("Completion Rate", f"{completion_rate:.1f}%")
st.divider()
st.header("🔍 Filter Tasks")
filter_option = st.radio(
"Show:",
['All Tasks', 'Active Tasks', 'Completed Tasks'],
index=['all', 'active', 'completed'].index(st.session_state.filter)
)
st.session_state.filter = ['all', 'active', 'completed'][['All Tasks', 'Active Tasks', 'Completed Tasks'].index(filter_option)]
st.divider()
st.header("🎯 Priority")
priority_filter = st.multiselect(
"Filter by priority:",
['High', 'Medium', 'Low'],
default=['High', 'Medium', 'Low']
)
st.divider()
if st.button("🗑️ Clear Completed", type="secondary"):
st.session_state.todos = utils.clear_completed_todos(st.session_state.todos)
st.rerun()
# Main content area
col1, col2 = st.columns([2, 1])
with col1:
st.header("📋 Task List")
# Search bar
search_query = st.text_input("🔎 Search tasks...", placeholder="Type to search...")
# Filter and search todos
filtered_todos = utils.filter_todos(st.session_state.todos, st.session_state.filter, search_query, priority_filter)
if not filtered_todos:
st.info("No tasks found. Add a new task to get started!")
else:
for todo in filtered_todos:
with st.container():
col_task, col_actions = st.columns([4, 1])
with col_task:
# Create a unique key for each todo
key = f"todo_{todo['id']}"
# Display todo based on whether it's being edited
if st.session_state.editing_id == todo['id']:
# Edit mode
edited_text = st.text_input(
"Edit task:",
value=todo['text'],
key=f"edit_{todo['id']}"
)
edited_priority = st.selectbox(
"Priority:",
['High', 'Medium', 'Low'],
index=['High', 'Medium', 'Low'].index(todo['priority']),
key=f"priority_{todo['id']}"
)
edited_date = st.date_input(
"Due date:",
value=datetime.strptime(todo['due_date'], '%Y-%m-%d').date(),
key=f"date_{todo['id']}"
)
col_save, col_cancel = st.columns(2)
with col_save:
if st.button("💾 Save", key=f"save_{todo['id']}", type="primary"):
st.session_state.todos = utils.update_todo(
st.session_state.todos,
todo['id'],
edited_text,
edited_priority,
edited_date.strftime('%Y-%m-%d')
)
st.session_state.editing_id = None
st.rerun()
with col_cancel:
if st.button("❌ Cancel", key=f"cancel_{todo['id']}"):
st.session_state.editing_id = None
st.rerun()
else:
# Display mode
completed = st.checkbox(
todo['text'],
value=todo['completed'],
key=f"check_{todo['id']}",
help=f"Priority: {todo['priority']} | Due: {todo['due_date']}"
)
if completed != todo['completed']:
st.session_state.todos = utils.toggle_todo(st.session_state.todos, todo['id'])
st.rerun()
# Show priority and due date
priority_color = {'High': '🔴', 'Medium': '🟡', 'Low': '🟢'}
st.markdown(
f"{priority_color[todo['priority']]} {todo['priority']} Priority | 📅 Due: {todo['due_date']}",
unsafe_allow_html=True
)
with col_actions:
if not todo['completed'] and st.session_state.editing_id != todo['id']:
if st.button("✏️", key=f"edit_btn_{todo['id']}", help="Edit task"):
st.session_state.editing_id = todo['id']
st.rerun()
if st.button("🗑️", key=f"delete_{todo['id']}", help="Delete task"):
st.session_state.todos = utils.delete_todo(st.session_state.todos, todo['id'])
st.rerun()
st.divider()
with col2:
st.header("➕ Add New Task")
with st.form("add_todo_form"):
task_text = st.text_area(
"Task description:",
placeholder="Enter your task here...",
height=100
)
priority = st.selectbox(
"Priority:",
['High', 'Medium', 'Low'],
index=1
)
due_date = st.date_input(
"Due date:",
value=date.today()
)
submit_button = st.form_submit_button("Add Task", type="primary")
if submit_button and task_text.strip():
new_todo = utils.create_todo(
task_text.strip(),
priority,
due_date.strftime('%Y-%m-%d')
)
st.session_state.todos.append(new_todo)
st.rerun()
st.success("Task added successfully!")
st.divider()
st.header("📈 Progress")
if stats['total'] > 0:
# Progress bar
progress_value = stats['completed'] / stats['total']
st.progress(progress_value)
st.caption(f"{stats['completed']} of {stats['total']} tasks completed")
# Priority breakdown
st.subheader("Priority Breakdown")
priority_stats = utils.get_priority_stats(st.session_state.todos)
for priority in ['High', 'Medium', 'Low']:
if priority_stats[priority] > 0:
st.write(f"🔴 {priority}: {priority_stats[priority]} tasks")
# Footer
st.markdown("---")
st.markdown(
""
"💡 Tip: Click on a task to mark it complete, use the edit button to modify, or delete when done!"
"
",
unsafe_allow_html=True
)
if __name__ == "__main__":
main()