import streamlit as st
import pandas as pd
from datetime import datetime
import time
import os
from io import BytesIO
from fpdf import FPDF
from apscheduler.schedulers.background import BackgroundScheduler
from plyer import notification
import plotly.express as px
# --- PAGE CONFIGURATION ---
st.set_page_config(page_title="The Task Tracker", page_icon="โ
", layout="wide")
# --- THEME CSS (Navy, Black, Gold) ---
st.markdown("""
""", unsafe_allow_html=True)
# --- BACKEND FUNCTIONS ---
DATA_FILE = "task_tracker_elite.csv"
def load_data():
if os.path.exists(DATA_FILE):
df = pd.read_csv(DATA_FILE)
if "Category" not in df.columns:
df["Category"] = "General"
return df
else:
return pd.DataFrame(columns=["Date", "Category", "Task", "Status"])
def save_data(df):
df.to_csv(DATA_FILE, index=False)
def trigger_notification():
try:
notification.notify(
title='The Task Tracker',
message='Execution is key. Update your progress.',
timeout=10
)
except:
pass
def to_excel(df):
output = BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
df.to_excel(writer, index=False, sheet_name='Sheet1')
return output.getvalue()
def to_pdf(df, start_date, end_date):
pdf = FPDF()
pdf.add_page()
pdf.set_font("Times", 'B', 20)
pdf.set_text_color(0, 31, 63)
pdf.cell(200, 15, txt="PERFORMANCE REPORT", ln=1, align='C')
pdf.set_font("Times", 'I', 12)
pdf.cell(200, 10, txt=f"Period: {start_date} to {end_date}", ln=1, align='C')
pdf.set_text_color(0, 0, 0)
pdf.set_font("Times", size=11)
pdf.ln(10)
cols = ["Date", "Category", "Task", "Status"]
pdf.set_fill_color(220, 220, 220)
for col in cols:
pdf.cell(45, 10, col, 1, 0, 'C', True)
pdf.ln()
for _, row in df.iterrows():
pdf.cell(45, 10, str(row['Date']), 1)
pdf.cell(45, 10, str(row['Category']), 1)
pdf.cell(45, 10, str(row['Task'])[:20], 1)
pdf.cell(45, 10, str(row['Status']), 1)
pdf.ln()
return pdf.output(dest='S').encode('latin-1')
# --- SCHEDULER ---
if 'scheduler_active' not in st.session_state:
scheduler = BackgroundScheduler()
scheduler.add_job(trigger_notification, 'cron', hour=21, minute=0)
scheduler.start()
st.session_state['scheduler_active'] = True
# --- UI LOGIC ---
# 1. UPDATED HEADER & TAGLINE
st.markdown("""
""", unsafe_allow_html=True)
df = load_data()
today_str = datetime.now().strftime("%Y-%m-%d")
# 2. UPDATED TAB NAMES
tab_planner, tab_analytics = st.tabs(["๐ Daily Task", "๐ Performance Metrics"])
# --- TAB 1: DAILY TASK ---
with tab_planner:
st.markdown("### ๐ Plan Your Execution")
with st.container():
c1, c2, c3 = st.columns([2, 1, 1])
with c1:
new_task = st.text_input("Task Description", placeholder="What is the next objective?")
with c2:
category = st.selectbox("Category", ["Work ๐ผ", "Personal ๐ ", "Finance ๐ฐ", "Health ๐ช", "Priority โก"])
with c3:
st.write("")
st.write("")
add_btn = st.button("ADD TASK", use_container_width=True)
if add_btn and new_task:
clean_cat = category.split(" ")[0]
new_entry = pd.DataFrame([{"Date": today_str, "Category": clean_cat, "Task": new_task, "Status": "Pending"}])
df = pd.concat([df, new_entry], ignore_index=True)
save_data(df)
st.toast("Task successfully added.", icon="โ
")
time.sleep(0.5)
st.rerun()
st.markdown("---")
today_tasks = df[df['Date'] == today_str]
if not today_tasks.empty:
total_today = len(today_tasks)
completed_count = len(today_tasks[today_tasks['Status'] == "Completed"])
progress_val = int((completed_count / total_today) * 100) if total_today > 0 else 0
st.write(f"### ๐ Daily Discipline: {progress_val}%")
st.progress(progress_val)
categories = today_tasks['Category'].unique()
with st.form("status_update_form"):
for cat in categories:
st.markdown(f"#### ๐น {cat}")
cat_tasks = today_tasks[today_tasks['Category'] == cat]
for index, row in cat_tasks.iterrows():
c_task, c_status = st.columns([3, 2])
with c_task:
if row['Status'] == "Completed":
st.markdown(f"โ
~~{row['Task']}~~")
elif row['Status'] == "Missed":
st.markdown(f"โ **{row['Task']}**")
else:
st.markdown(f"**{row['Task']}**")
with c_status:
options = ["Pending", "Completed", "Missed"]
try:
default_ix = options.index(row['Status'])
except:
default_ix = 0
st.radio("Status", options, key=f"status_{index}", index=default_ix, horizontal=True, label_visibility="collapsed")
st.write("")
if st.form_submit_button("CONFIRM PROGRESS"):
# Save changes
for index, row in today_tasks.iterrows():
key = f"status_{index}"
if key in st.session_state:
df.at[index, 'Status'] = st.session_state[key]
save_data(df)
# 3. NEW YEAR EVE EFFECT LOGIC
# Trigger massive celebration on any update to simulate the "Sky at New Year"
st.balloons() # Rising crackers
st.snow() # Falling glitter/ash from crackers
st.toast("๐ ๐ฅ ๐งจ BOOM! Progress Recorded! ๐งจ ๐ฅ ๐", icon="โจ")
current_completed = len(df[(df['Date'] == today_str) & (df['Status'] == "Completed")])
if current_completed == total_today and total_today > 0:
st.success("๐ EXECUTION COMPLETE! You mastered the day.")
else:
st.info("Progress updated. Keep pushing.")
time.sleep(2)
st.rerun()
else:
st.info("No tasks defined. Start by planning your day above.")
# --- TAB 2: PERFORMANCE METRICS ---
with tab_analytics:
st.header("๐ Performance Metrics")
st.markdown("##### ๐๏ธ Select Reporting Period")
c_date1, c_date2 = st.columns(2)
start_date = c_date1.date_input("Start Date")
end_date = c_date2.date_input("End Date")
st.markdown("---")
if not df.empty:
mask = (df['Date'] >= str(start_date)) & (df['Date'] <= str(end_date))
filtered_df = df.loc[mask]
if not filtered_df.empty:
total_all = len(filtered_df)
total_done = len(filtered_df[filtered_df['Status'] == "Completed"])
total_missed = len(filtered_df[filtered_df['Status'] == "Missed"])
c1, c2, c3 = st.columns(3)
c1.metric("Total Tasks", total_all)
c2.metric("Executed (Done)", total_done)
c3.metric("Missed (Failed)", total_missed)
st.write("")
g1, g2 = st.columns(2)
with g1:
st.subheader("Consistency Chart")
daily_stats = filtered_df.groupby(['Date', 'Status']).size().reset_index(name='Count')
color_map = {
"Completed": "#001f3f",
"Missed": "#000000",
"Pending": "#808080"
}
fig_bar = px.bar(
daily_stats, x="Date", y="Count", color="Status",
barmode="group", color_discrete_map=color_map,
title="Daily Execution"
)
fig_bar.update_layout(font_family="Times New Roman")
st.plotly_chart(fig_bar, use_container_width=True)
with g2:
st.subheader("Category Breakdown")
cat_counts = filtered_df['Category'].value_counts().reset_index()
cat_counts.columns = ['Category', 'Count']
fig_pie = px.pie(
cat_counts, values='Count', names='Category', hole=0.4,
color_discrete_sequence=px.colors.sequential.Blues_r,
title="Focus Distribution"
)
fig_pie.update_layout(font_family="Times New Roman")
st.plotly_chart(fig_pie, use_container_width=True)
st.write("### ๐ฅ Download Reports")
d1, d2 = st.columns(2)
d1.download_button(
"Export Excel Log",
data=to_excel(filtered_df),
file_name=f"Task_Data_{start_date}_{end_date}.xlsx"
)
d2.download_button(
"Export PDF Report",
data=to_pdf(filtered_df, start_date, end_date),
file_name=f"Task_Report_{start_date}_{end_date}.pdf"
)
else:
st.warning(f"No data found between {start_date} and {end_date}.")
else:
st.info("No data available in database.")