Ezhumalai13 commited on
Commit
9492f63
Β·
verified Β·
1 Parent(s): 736e5e7

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +366 -0
  2. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from datetime import datetime
4
+ import time
5
+ import os
6
+ from io import BytesIO
7
+ from fpdf import FPDF
8
+ from apscheduler.schedulers.background import BackgroundScheduler
9
+ from plyer import notification
10
+ import plotly.express as px
11
+
12
+ # --- PAGE CONFIGURATION ---
13
+ st.set_page_config(page_title="The Task Tracker", page_icon="βœ…", layout="wide")
14
+
15
+ # --- THEME CSS (Navy, Black, Gold) ---
16
+ st.markdown("""
17
+ <style>
18
+ /* GLOBAL FONT */
19
+ html, body, [class*="css"] {
20
+ font-family: 'Times New Roman', Times, serif;
21
+ }
22
+
23
+ /* BACKGROUND */
24
+ .stApp {
25
+ background-color: #F8F9FA;
26
+ color: #000000;
27
+ }
28
+
29
+ /* --- HEADER CSS --- */
30
+ .header-container {
31
+ background: linear-gradient(135deg, #000000 0%, #001f3f 100%);
32
+ padding: 30px;
33
+ border-radius: 12px;
34
+ color: white;
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: flex-start;
38
+ border-bottom: 4px solid #D4AF37;
39
+ margin-bottom: 30px;
40
+ box-shadow: 0 10px 20px rgba(0,0,0,0.3);
41
+ }
42
+
43
+ .svg-logo-container {
44
+ margin-right: 30px;
45
+ filter: drop-shadow(0px 0px 8px rgba(212, 175, 55, 0.5));
46
+ }
47
+
48
+ .title-block h1 {
49
+ font-family: 'Times New Roman', serif;
50
+ font-weight: 800;
51
+ letter-spacing: 2px;
52
+ margin: 0;
53
+ font-size: 3rem;
54
+ text-transform: uppercase;
55
+ color: #FFFFFF;
56
+ }
57
+
58
+ .title-block p {
59
+ font-size: 1.2rem;
60
+ font-style: italic;
61
+ color: #D4AF37;
62
+ margin-top: 10px;
63
+ font-weight: 500;
64
+ }
65
+
66
+ /* BUTTONS */
67
+ .stButton>button {
68
+ background-color: #001f3f;
69
+ color: white;
70
+ border-radius: 2px;
71
+ border: 1px solid #000000;
72
+ font-weight: bold;
73
+ font-size: 16px;
74
+ transition: 0.3s;
75
+ }
76
+ .stButton>button:hover {
77
+ background-color: #003366;
78
+ border-color: #D4AF37;
79
+ }
80
+
81
+ /* TABS */
82
+ .stTabs [data-baseweb="tab-list"] { gap: 10px; }
83
+ .stTabs [data-baseweb="tab"] {
84
+ height: 50px;
85
+ background-color: #E0E0E0;
86
+ border-radius: 4px 4px 0px 0px;
87
+ color: #000000;
88
+ font-weight: bold;
89
+ }
90
+ .stTabs [aria-selected="true"] {
91
+ background-color: #001f3f;
92
+ color: white;
93
+ border-bottom: 3px solid #D4AF37;
94
+ }
95
+
96
+ /* METRICS */
97
+ div[data-testid="stMetricValue"] {
98
+ color: #001f3f;
99
+ }
100
+ </style>
101
+ """, unsafe_allow_html=True)
102
+
103
+ # --- BACKEND FUNCTIONS ---
104
+ DATA_FILE = "task_tracker_elite.csv"
105
+
106
+ def load_data():
107
+ if os.path.exists(DATA_FILE):
108
+ df = pd.read_csv(DATA_FILE)
109
+ if "Category" not in df.columns:
110
+ df["Category"] = "General"
111
+ return df
112
+ else:
113
+ return pd.DataFrame(columns=["Date", "Category", "Task", "Status"])
114
+
115
+ def save_data(df):
116
+ df.to_csv(DATA_FILE, index=False)
117
+
118
+ def trigger_notification():
119
+ try:
120
+ notification.notify(
121
+ title='The Task Tracker',
122
+ message='Execution is key. Update your progress.',
123
+ timeout=10
124
+ )
125
+ except:
126
+ pass
127
+
128
+ def to_excel(df):
129
+ output = BytesIO()
130
+ with pd.ExcelWriter(output, engine='openpyxl') as writer:
131
+ df.to_excel(writer, index=False, sheet_name='Sheet1')
132
+ return output.getvalue()
133
+
134
+ def to_pdf(df, start_date, end_date):
135
+ pdf = FPDF()
136
+ pdf.add_page()
137
+ pdf.set_font("Times", 'B', 20)
138
+ pdf.set_text_color(0, 31, 63)
139
+ pdf.cell(200, 15, txt="PERFORMANCE REPORT", ln=1, align='C')
140
+
141
+ pdf.set_font("Times", 'I', 12)
142
+ pdf.cell(200, 10, txt=f"Period: {start_date} to {end_date}", ln=1, align='C')
143
+
144
+ pdf.set_text_color(0, 0, 0)
145
+ pdf.set_font("Times", size=11)
146
+ pdf.ln(10)
147
+
148
+ cols = ["Date", "Category", "Task", "Status"]
149
+ pdf.set_fill_color(220, 220, 220)
150
+ for col in cols:
151
+ pdf.cell(45, 10, col, 1, 0, 'C', True)
152
+ pdf.ln()
153
+
154
+ for _, row in df.iterrows():
155
+ pdf.cell(45, 10, str(row['Date']), 1)
156
+ pdf.cell(45, 10, str(row['Category']), 1)
157
+ pdf.cell(45, 10, str(row['Task'])[:20], 1)
158
+ pdf.cell(45, 10, str(row['Status']), 1)
159
+ pdf.ln()
160
+ return pdf.output(dest='S').encode('latin-1')
161
+
162
+ # --- SCHEDULER ---
163
+ if 'scheduler_active' not in st.session_state:
164
+ scheduler = BackgroundScheduler()
165
+ scheduler.add_job(trigger_notification, 'cron', hour=21, minute=0)
166
+ scheduler.start()
167
+ st.session_state['scheduler_active'] = True
168
+
169
+ # --- UI LOGIC ---
170
+
171
+ # 1. UPDATED HEADER & TAGLINE
172
+ st.markdown("""
173
+ <div class="header-container">
174
+ <div class="svg-logo-container">
175
+ <svg width="100px" height="100px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
176
+ <path d="M6 3L6 21" stroke="#001f3f" stroke-width="2" stroke-linecap="round"/>
177
+ <path d="M18 3L18 21" stroke="#001f3f" stroke-width="2" stroke-linecap="round"/>
178
+ <path d="M6 7H18" stroke="#001f3f" stroke-width="2" stroke-linecap="round"/>
179
+ <path d="M6 12H18" stroke="#001f3f" stroke-width="2" stroke-linecap="round"/>
180
+ <path d="M6 17H18" stroke="#001f3f" stroke-width="2" stroke-linecap="round"/>
181
+ <circle cx="12" cy="8" r="2" fill="#D4AF37"/>
182
+ <path d="M12 10V14L10 16.5" stroke="#D4AF37" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
183
+ <path d="M12 14L14 16.5" stroke="#D4AF37" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
184
+ <path d="M10 11L12 10L14 11" stroke="#D4AF37" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
185
+ <path d="M14 11L16 8" stroke="#D4AF37" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
186
+ </svg>
187
+ </div>
188
+ <div class="title-block">
189
+ <h1>THE TASK TRACKER</h1>
190
+ <p>"Planning, Focus, Discipline & Execution – these are the Mantras of the life."</p>
191
+ </div>
192
+ </div>
193
+ """, unsafe_allow_html=True)
194
+
195
+ df = load_data()
196
+ today_str = datetime.now().strftime("%Y-%m-%d")
197
+
198
+ # 2. UPDATED TAB NAMES
199
+ tab_planner, tab_analytics = st.tabs(["πŸ“ Daily Task", "πŸ“Š Performance Metrics"])
200
+
201
+ # --- TAB 1: DAILY TASK ---
202
+ with tab_planner:
203
+ st.markdown("### πŸ“‹ Plan Your Execution")
204
+ with st.container():
205
+ c1, c2, c3 = st.columns([2, 1, 1])
206
+ with c1:
207
+ new_task = st.text_input("Task Description", placeholder="What is the next objective?")
208
+ with c2:
209
+ category = st.selectbox("Category", ["Work πŸ’Ό", "Personal 🏠", "Finance πŸ’°", "Health πŸ’ͺ", "Priority ⚑"])
210
+ with c3:
211
+ st.write("")
212
+ st.write("")
213
+ add_btn = st.button("ADD TASK", use_container_width=True)
214
+
215
+ if add_btn and new_task:
216
+ clean_cat = category.split(" ")[0]
217
+ new_entry = pd.DataFrame([{"Date": today_str, "Category": clean_cat, "Task": new_task, "Status": "Pending"}])
218
+ df = pd.concat([df, new_entry], ignore_index=True)
219
+ save_data(df)
220
+ st.toast("Task successfully added.", icon="βœ…")
221
+ time.sleep(0.5)
222
+ st.rerun()
223
+
224
+ st.markdown("---")
225
+
226
+ today_tasks = df[df['Date'] == today_str]
227
+
228
+ if not today_tasks.empty:
229
+ total_today = len(today_tasks)
230
+ completed_count = len(today_tasks[today_tasks['Status'] == "Completed"])
231
+ progress_val = int((completed_count / total_today) * 100) if total_today > 0 else 0
232
+
233
+ st.write(f"### πŸ“‰ Daily Discipline: {progress_val}%")
234
+ st.progress(progress_val)
235
+
236
+ categories = today_tasks['Category'].unique()
237
+
238
+ with st.form("status_update_form"):
239
+ for cat in categories:
240
+ st.markdown(f"#### πŸ”Ή {cat}")
241
+ cat_tasks = today_tasks[today_tasks['Category'] == cat]
242
+
243
+ for index, row in cat_tasks.iterrows():
244
+ c_task, c_status = st.columns([3, 2])
245
+ with c_task:
246
+ if row['Status'] == "Completed":
247
+ st.markdown(f"βœ… ~~{row['Task']}~~")
248
+ elif row['Status'] == "Missed":
249
+ st.markdown(f"❌ **{row['Task']}**")
250
+ else:
251
+ st.markdown(f"**{row['Task']}**")
252
+
253
+ with c_status:
254
+ options = ["Pending", "Completed", "Missed"]
255
+ try:
256
+ default_ix = options.index(row['Status'])
257
+ except:
258
+ default_ix = 0
259
+ st.radio("Status", options, key=f"status_{index}", index=default_ix, horizontal=True, label_visibility="collapsed")
260
+
261
+ st.write("")
262
+ if st.form_submit_button("CONFIRM PROGRESS"):
263
+ # Save changes
264
+ for index, row in today_tasks.iterrows():
265
+ key = f"status_{index}"
266
+ if key in st.session_state:
267
+ df.at[index, 'Status'] = st.session_state[key]
268
+ save_data(df)
269
+
270
+ # 3. NEW YEAR EVE EFFECT LOGIC
271
+ # Trigger massive celebration on any update to simulate the "Sky at New Year"
272
+ st.balloons() # Rising crackers
273
+ st.snow() # Falling glitter/ash from crackers
274
+ st.toast("πŸŽ† πŸ’₯ 🧨 BOOM! Progress Recorded! 🧨 πŸ’₯ πŸŽ†", icon="✨")
275
+
276
+ current_completed = len(df[(df['Date'] == today_str) & (df['Status'] == "Completed")])
277
+
278
+ if current_completed == total_today and total_today > 0:
279
+ st.success("πŸ† EXECUTION COMPLETE! You mastered the day.")
280
+ else:
281
+ st.info("Progress updated. Keep pushing.")
282
+
283
+ time.sleep(2)
284
+ st.rerun()
285
+ else:
286
+ st.info("No tasks defined. Start by planning your day above.")
287
+
288
+ # --- TAB 2: PERFORMANCE METRICS ---
289
+ with tab_analytics:
290
+ st.header("πŸ“Š Performance Metrics")
291
+
292
+ st.markdown("##### πŸ—“οΈ Select Reporting Period")
293
+ c_date1, c_date2 = st.columns(2)
294
+ start_date = c_date1.date_input("Start Date")
295
+ end_date = c_date2.date_input("End Date")
296
+
297
+ st.markdown("---")
298
+
299
+ if not df.empty:
300
+ mask = (df['Date'] >= str(start_date)) & (df['Date'] <= str(end_date))
301
+ filtered_df = df.loc[mask]
302
+
303
+ if not filtered_df.empty:
304
+ total_all = len(filtered_df)
305
+ total_done = len(filtered_df[filtered_df['Status'] == "Completed"])
306
+ total_missed = len(filtered_df[filtered_df['Status'] == "Missed"])
307
+
308
+ c1, c2, c3 = st.columns(3)
309
+ c1.metric("Total Tasks", total_all)
310
+ c2.metric("Executed (Done)", total_done)
311
+ c3.metric("Missed (Failed)", total_missed)
312
+
313
+ st.write("")
314
+
315
+ g1, g2 = st.columns(2)
316
+
317
+ with g1:
318
+ st.subheader("Consistency Chart")
319
+ daily_stats = filtered_df.groupby(['Date', 'Status']).size().reset_index(name='Count')
320
+
321
+ color_map = {
322
+ "Completed": "#001f3f",
323
+ "Missed": "#000000",
324
+ "Pending": "#808080"
325
+ }
326
+
327
+ fig_bar = px.bar(
328
+ daily_stats, x="Date", y="Count", color="Status",
329
+ barmode="group", color_discrete_map=color_map,
330
+ title="Daily Execution"
331
+ )
332
+ fig_bar.update_layout(font_family="Times New Roman")
333
+ st.plotly_chart(fig_bar, use_container_width=True)
334
+
335
+ with g2:
336
+ st.subheader("Category Breakdown")
337
+ cat_counts = filtered_df['Category'].value_counts().reset_index()
338
+ cat_counts.columns = ['Category', 'Count']
339
+
340
+ fig_pie = px.pie(
341
+ cat_counts, values='Count', names='Category', hole=0.4,
342
+ color_discrete_sequence=px.colors.sequential.Blues_r,
343
+ title="Focus Distribution"
344
+ )
345
+ fig_pie.update_layout(font_family="Times New Roman")
346
+ st.plotly_chart(fig_pie, use_container_width=True)
347
+
348
+ st.write("### πŸ“₯ Download Reports")
349
+ d1, d2 = st.columns(2)
350
+
351
+ d1.download_button(
352
+ "Export Excel Log",
353
+ data=to_excel(filtered_df),
354
+ file_name=f"Task_Data_{start_date}_{end_date}.xlsx"
355
+ )
356
+
357
+ d2.download_button(
358
+ "Export PDF Report",
359
+ data=to_pdf(filtered_df, start_date, end_date),
360
+ file_name=f"Task_Report_{start_date}_{end_date}.pdf"
361
+ )
362
+
363
+ else:
364
+ st.warning(f"No data found between {start_date} and {end_date}.")
365
+ else:
366
+ st.info("No data available in database.")
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ fpdf
4
+ apscheduler
5
+ plyer
6
+ plotly
7
+ openpyxl