Upload 3 files
Browse files- app.py +237 -0
- readme.md +52 -0
- requirements.txt +1 -0
app.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from datetime import datetime, timedelta, time
|
| 3 |
+
import calendar
|
| 4 |
+
import pandas as pd
|
| 5 |
+
|
| 6 |
+
# Helper function to render the calendar for the selected month
|
| 7 |
+
def render_calendar(month, year):
|
| 8 |
+
st.write(f"### {calendar.month_name[month]} {year}")
|
| 9 |
+
weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
| 10 |
+
month_days = calendar.monthcalendar(year, month)
|
| 11 |
+
|
| 12 |
+
table = []
|
| 13 |
+
for week in month_days:
|
| 14 |
+
row = []
|
| 15 |
+
for day in week:
|
| 16 |
+
row.append(day if day != 0 else "")
|
| 17 |
+
table.append(row)
|
| 18 |
+
|
| 19 |
+
df = pd.DataFrame(table, columns=weekdays)
|
| 20 |
+
return df
|
| 21 |
+
|
| 22 |
+
# Display and interact with the tasks for a selected date
|
| 23 |
+
def log_task_for_date(selected_date):
|
| 24 |
+
if selected_date not in st.session_state:
|
| 25 |
+
st.session_state[selected_date] = []
|
| 26 |
+
|
| 27 |
+
st.write(f"### Tasks for {selected_date}")
|
| 28 |
+
|
| 29 |
+
task = st.text_input("Enter a task", key=f"task_input_{selected_date}")
|
| 30 |
+
category = st.selectbox("Select Category", ["Work", "Personal", "Urgent", "Other"], key=f"category_select_{selected_date}")
|
| 31 |
+
priority = st.selectbox("Select Priority", ["High", "Medium", "Low"], key=f"priority_select_{selected_date}")
|
| 32 |
+
due_date = st.date_input("Select Due Date", min_value=datetime.today(), key=f"due_date_input_{selected_date}")
|
| 33 |
+
|
| 34 |
+
# Custom time selection with 24-hour dropdown
|
| 35 |
+
time_options = [time(hour=h, minute=m).strftime("%H:%M") for h in range(24) for m in (0, 30)]
|
| 36 |
+
selected_time_str = st.selectbox(
|
| 37 |
+
"Select Due Time",
|
| 38 |
+
options=time_options,
|
| 39 |
+
index=time_options.index("09:00"),
|
| 40 |
+
key=f"due_time_input_{selected_date}"
|
| 41 |
+
)
|
| 42 |
+
due_time = datetime.strptime(selected_time_str, "%H:%M").time()
|
| 43 |
+
|
| 44 |
+
if st.button("Add Task", key=f"add_task_button_{selected_date}"):
|
| 45 |
+
task_info = {
|
| 46 |
+
"task": task,
|
| 47 |
+
"category": category,
|
| 48 |
+
"priority": priority,
|
| 49 |
+
"due_date": str(due_date),
|
| 50 |
+
"due_time": str(due_time),
|
| 51 |
+
"completed": False,
|
| 52 |
+
}
|
| 53 |
+
if task_info not in st.session_state[selected_date]:
|
| 54 |
+
st.session_state[selected_date].append(task_info)
|
| 55 |
+
st.success("Task added!")
|
| 56 |
+
else:
|
| 57 |
+
st.warning("Task already exists!")
|
| 58 |
+
|
| 59 |
+
if st.session_state[selected_date]:
|
| 60 |
+
st.write("**Current Tasks:**")
|
| 61 |
+
task_df = pd.DataFrame(st.session_state[selected_date])
|
| 62 |
+
task_df = task_df.sort_values(by=["priority", "due_date", "due_time"], ascending=[True, True, True])
|
| 63 |
+
|
| 64 |
+
for idx, row in task_df.iterrows():
|
| 65 |
+
task_str = f"{row['task']} - Category: {row['category']} | Priority: {row['priority']} | Due: {row['due_date']} {row['due_time']}"
|
| 66 |
+
if row['completed']:
|
| 67 |
+
task_str = f"β
{task_str}"
|
| 68 |
+
st.write(task_str)
|
| 69 |
+
mark_as_completed = st.checkbox(
|
| 70 |
+
f"Mark as completed",
|
| 71 |
+
key=f"complete_{selected_date}_{idx}",
|
| 72 |
+
value=row['completed']
|
| 73 |
+
)
|
| 74 |
+
if mark_as_completed and not row['completed']:
|
| 75 |
+
st.session_state[selected_date][idx]["completed"] = True
|
| 76 |
+
st.success(f"Task '{row['task']}' marked as completed!")
|
| 77 |
+
|
| 78 |
+
# Search and view tasks by date without needing to type
|
| 79 |
+
def view_tasks_by_date():
|
| 80 |
+
st.write("## π View Tasks by Date")
|
| 81 |
+
selected = st.date_input("Pick a Date to View Tasks", value=datetime.today())
|
| 82 |
+
selected_str = str(selected)
|
| 83 |
+
tasks = st.session_state.get(selected_str, [])
|
| 84 |
+
|
| 85 |
+
if tasks:
|
| 86 |
+
st.write(f"### Tasks for {selected_str}")
|
| 87 |
+
for idx, task in enumerate(tasks):
|
| 88 |
+
with st.expander(f"{'β
' if task['completed'] else ''}{task['task']}"):
|
| 89 |
+
st.write(f"**Category:** {task['category']}")
|
| 90 |
+
st.write(f"**Priority:** {task['priority']}")
|
| 91 |
+
st.write(f"**Due Date:** {task['due_date']}")
|
| 92 |
+
st.write(f"**Due Time:** {task['due_time']}")
|
| 93 |
+
st.write(f"**Completed:** {'Yes β
' if task['completed'] else 'No β'}")
|
| 94 |
+
else:
|
| 95 |
+
st.info("No tasks logged for this date.")
|
| 96 |
+
|
| 97 |
+
# Highlight today's date
|
| 98 |
+
def highlight_today(month, year):
|
| 99 |
+
today = datetime.today()
|
| 100 |
+
if today.month == month and today.year == year:
|
| 101 |
+
return today.day
|
| 102 |
+
return None
|
| 103 |
+
|
| 104 |
+
# Generate CSV data for tasks
|
| 105 |
+
def get_task_csv(scope, selected_date):
|
| 106 |
+
tasks = []
|
| 107 |
+
for date, task_list in st.session_state.items():
|
| 108 |
+
if isinstance(task_list, list):
|
| 109 |
+
if scope == "day" and date == selected_date:
|
| 110 |
+
tasks.extend(task_list)
|
| 111 |
+
elif scope == "month" and date.startswith(selected_date[:7]):
|
| 112 |
+
tasks.extend(task_list)
|
| 113 |
+
elif scope == "year" and date.startswith(selected_date[:4]):
|
| 114 |
+
tasks.extend(task_list)
|
| 115 |
+
df = pd.DataFrame(tasks)
|
| 116 |
+
return df.to_csv(index=False)
|
| 117 |
+
|
| 118 |
+
# Main Streamlit app with sidebar
|
| 119 |
+
def main():
|
| 120 |
+
# Apply custom CSS to set light grey background
|
| 121 |
+
st.markdown(
|
| 122 |
+
"""
|
| 123 |
+
<style>
|
| 124 |
+
/* Main background */
|
| 125 |
+
[data-testid="stAppViewContainer"] {
|
| 126 |
+
background-image: url('https://png.pngtree.com/thumb_back/fh260/background/20240916/pngtree-simple-orange-aesthetic-background-image_16213466.jpg');
|
| 127 |
+
background-size: cover;
|
| 128 |
+
background-position: center;
|
| 129 |
+
background-repeat: no-repeat;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
/* Sidebar background */
|
| 133 |
+
[data-testid="stSidebar"] > div:first-child {
|
| 134 |
+
background-image: url('https://st.depositphotos.com/2890321/51451/i/600/depositphotos_514519944-stock-photo-close-calendar-purple-table-background.jpg');
|
| 135 |
+
background-size: cover;
|
| 136 |
+
background-position: center;
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
/* Optional: semi-transparent overlay for content readability */
|
| 140 |
+
.main > div {
|
| 141 |
+
background-color: rgba(255, 255, 255, 0.85);
|
| 142 |
+
padding: 1rem;
|
| 143 |
+
border-radius: 12px;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
/* Styling sidebar links */
|
| 147 |
+
.sidebar-links img {
|
| 148 |
+
width: 20px;
|
| 149 |
+
margin-right: 10px;
|
| 150 |
+
vertical-align: middle;
|
| 151 |
+
}
|
| 152 |
+
.sidebar-links a {
|
| 153 |
+
text-decoration: none;
|
| 154 |
+
display: inline-block;
|
| 155 |
+
color: white;
|
| 156 |
+
font-weight: bold;
|
| 157 |
+
margin-bottom: 8px;
|
| 158 |
+
}
|
| 159 |
+
</style>
|
| 160 |
+
""",
|
| 161 |
+
unsafe_allow_html=True
|
| 162 |
+
)
|
| 163 |
+
|
| 164 |
+
st.title("π
Dynamic Calendar & Task Logger")
|
| 165 |
+
|
| 166 |
+
# Sidebar for navigation
|
| 167 |
+
st.sidebar.title("Navigation")
|
| 168 |
+
app_mode = st.sidebar.radio("Choose an Option", ("Log Tasks", "View Tasks", "Download Task Data"))
|
| 169 |
+
|
| 170 |
+
# Connect with Me Section
|
| 171 |
+
st.sidebar.markdown("## π¨βπ» Connect with Me")
|
| 172 |
+
st.sidebar.markdown("""
|
| 173 |
+
<div class="sidebar-links">
|
| 174 |
+
<a href="https://github.com/marianadeem755" target="_blank">
|
| 175 |
+
<img src="https://cdn-icons-png.flaticon.com/512/25/25231.png"> GitHub
|
| 176 |
+
</a><br>
|
| 177 |
+
<a href="https://www.kaggle.com/marianadeem755" target="_blank">
|
| 178 |
+
<img src="https://cdn4.iconfinder.com/data/icons/logos-and-brands/512/189_Kaggle_logo_logos-512.png"> Kaggle
|
| 179 |
+
</a><br>
|
| 180 |
+
<a href="mailto:marianadeem755@gmail.com">
|
| 181 |
+
<img src="https://cdn-icons-png.flaticon.com/512/561/561127.png"> Email
|
| 182 |
+
</a><br>
|
| 183 |
+
<a href="https://huggingface.co/maria355" target="_blank">
|
| 184 |
+
<img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg"> Hugging Face
|
| 185 |
+
</a>
|
| 186 |
+
</div>
|
| 187 |
+
""", unsafe_allow_html=True)
|
| 188 |
+
|
| 189 |
+
if "initialized" not in st.session_state:
|
| 190 |
+
st.session_state.initialized = True
|
| 191 |
+
|
| 192 |
+
today = datetime.today()
|
| 193 |
+
month = st.selectbox("Select Month", list(range(1, 13)), index=today.month - 1)
|
| 194 |
+
year = st.selectbox("Select Year", list(range(today.year - 5, today.year + 6)), index=5)
|
| 195 |
+
|
| 196 |
+
calendar_df = render_calendar(month, year)
|
| 197 |
+
today_day = highlight_today(month, year)
|
| 198 |
+
|
| 199 |
+
for col in calendar_df.columns:
|
| 200 |
+
calendar_df[col] = calendar_df[col].apply(lambda x: f"**{x}**" if x == today_day else x)
|
| 201 |
+
|
| 202 |
+
st.table(calendar_df)
|
| 203 |
+
|
| 204 |
+
selected_date = st.date_input("Select a Date to Add Tasks", today)
|
| 205 |
+
|
| 206 |
+
if app_mode == "Log Tasks":
|
| 207 |
+
log_task_for_date(str(selected_date))
|
| 208 |
+
|
| 209 |
+
elif app_mode == "View Tasks":
|
| 210 |
+
view_tasks_by_date()
|
| 211 |
+
|
| 212 |
+
elif app_mode == "Download Task Data":
|
| 213 |
+
col1, col2, col3 = st.columns(3)
|
| 214 |
+
with col1:
|
| 215 |
+
st.download_button(
|
| 216 |
+
"Download for Day π
",
|
| 217 |
+
data=get_task_csv("day", str(selected_date)),
|
| 218 |
+
file_name=f"tasks_day_{selected_date}.csv",
|
| 219 |
+
mime="text/csv"
|
| 220 |
+
)
|
| 221 |
+
with col2:
|
| 222 |
+
st.download_button(
|
| 223 |
+
"Download for Month ποΈ",
|
| 224 |
+
data=get_task_csv("month", str(selected_date)),
|
| 225 |
+
file_name=f"tasks_month_{selected_date.strftime('%Y-%m')}.csv",
|
| 226 |
+
mime="text/csv"
|
| 227 |
+
)
|
| 228 |
+
with col3:
|
| 229 |
+
st.download_button(
|
| 230 |
+
"Download for Year π",
|
| 231 |
+
data=get_task_csv("year", str(selected_date)),
|
| 232 |
+
file_name=f"tasks_year_{selected_date.strftime('%Y')}.csv",
|
| 233 |
+
mime="text/csv"
|
| 234 |
+
)
|
| 235 |
+
|
| 236 |
+
if __name__ == "__main__":
|
| 237 |
+
main()
|
readme.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# π
Dynamic Calendar and Task Logger
|
| 2 |
+
|
| 3 |
+
A **Streamlit**-based web application that allows users to log, view and manage tasks dynamically using an interactive calendar interface. This app is designed to help users stay organized by categorizing tasks, setting priorities and tracking due dates and times and then Download Files on which they include their tasks on daily, monthly and yearly basis.
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
## π Features
|
| 8 |
+
|
| 9 |
+
- **Dynamic Calendar View**: Displays a calendar for the selected month and year.
|
| 10 |
+
- **Task Logging**: Add tasks with details such as category, priority, due date, and time.
|
| 11 |
+
- **Task Management**:
|
| 12 |
+
- Mark tasks as completed.
|
| 13 |
+
- View tasks for a specific date.
|
| 14 |
+
- **Task Export**: Download tasks as CSV files for a specific day, month, or year.
|
| 15 |
+
- **Responsive Sidebar**: Navigate between logging tasks, viewing tasks and downloading task data.
|
| 16 |
+
|
| 17 |
+
---
|
| 18 |
+
|
| 19 |
+
## π οΈ Installation
|
| 20 |
+
1. Install the required dependencies:
|
| 21 |
+
```bash
|
| 22 |
+
pip install -r requirements.txt
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
2. Run the Streamlit app:
|
| 26 |
+
```bash
|
| 27 |
+
streamlit run app.py
|
| 28 |
+
```
|
| 29 |
+
---
|
| 30 |
+
|
| 31 |
+
## π How to Use
|
| 32 |
+
|
| 33 |
+
1. **Log Tasks**:
|
| 34 |
+
- Select a date from the calendar.
|
| 35 |
+
- Enter task details such as name, category, priority, due date, and time.
|
| 36 |
+
- Click "Add Task" to save the task.
|
| 37 |
+
|
| 38 |
+
2. **View Tasks**:
|
| 39 |
+
- Navigate to the "View Tasks" section.
|
| 40 |
+
- Select a date to view all tasks logged for that day.
|
| 41 |
+
- Complete Detailes of taht Task shows by clicking on that Task
|
| 42 |
+
|
| 43 |
+
3. **Download Task Data**:
|
| 44 |
+
- Navigate to the "Download Task Data" section.
|
| 45 |
+
- Download tasks for a specific day, month or year in CSV format.
|
| 46 |
+
|
| 47 |
+
---
|
| 48 |
+
|
| 49 |
+
## π Acknowledgments
|
| 50 |
+
|
| 51 |
+
- Built with [Streamlit](https://streamlit.io/).
|
| 52 |
+
```
|
requirements.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
streamlit
|