88 lines
2.5 KiB
Python
88 lines
2.5 KiB
Python
import streamlit as st
|
|
from streamlit_calendar import calendar
|
|
import pandas as pd
|
|
import database
|
|
import datetime
|
|
|
|
# --- Configuration ---
|
|
st.set_page_config(page_title="Work Tracker", layout="wide")
|
|
|
|
# --- Database Init ---
|
|
if "db_initialized" not in st.session_state:
|
|
database.init_db()
|
|
st.session_state["db_initialized"] = True
|
|
|
|
# --- UI Layout ---
|
|
st.title("📅 Work Hours Tracker")
|
|
|
|
col1, col2 = st.columns([2, 1])
|
|
|
|
# --- Calendar Section ---
|
|
with col1:
|
|
st.subheader("Select Work Days")
|
|
|
|
# Fetch existing data to populate calendar
|
|
df = database.get_all_days()
|
|
|
|
# Format events for streamlit-calendar
|
|
events = []
|
|
if not df.empty:
|
|
for date_str in df['date']:
|
|
events.append({
|
|
"title": "Worked",
|
|
"start": date_str,
|
|
"allDay": True,
|
|
"color": "#4CAF50" # Green for worked days
|
|
})
|
|
|
|
# Calendar options
|
|
calendar_options = {
|
|
"headerToolbar": {
|
|
"left": "today prev,next",
|
|
"center": "title",
|
|
"right": "dayGridMonth,dayGridWeek"
|
|
},
|
|
"initialView": "dayGridMonth",
|
|
"selectable": True,
|
|
}
|
|
|
|
# Render Calendar
|
|
cal = calendar(events=events, options=calendar_options, key="calendar")
|
|
|
|
# Handle Click Events
|
|
if cal.get("callback") == "dateClick":
|
|
clicked_date = cal["dateClick"]["dateStr"]
|
|
database.toggle_day(clicked_date)
|
|
st.rerun() # Refresh to update calendar and stats
|
|
|
|
# --- Statistics Section ---
|
|
with col2:
|
|
st.subheader("Statistics")
|
|
|
|
if not df.empty:
|
|
# Convert to datetime
|
|
df['date'] = pd.to_datetime(df['date'])
|
|
df = df.sort_values('date')
|
|
|
|
# Calculate weekly stats
|
|
# Resample to weekly frequency (W-MON)
|
|
weekly_counts = df.resample('W-MON', on='date').size()
|
|
|
|
if not weekly_counts.empty:
|
|
avg_days_per_week = weekly_counts.mean()
|
|
st.metric("Avg Days / Week (Total)", f"{avg_days_per_week:.2f}")
|
|
|
|
# Plotting
|
|
st.line_chart(weekly_counts, use_container_width=True)
|
|
|
|
# Monthly breakdown
|
|
monthly_counts = df.resample('M', on='date').size()
|
|
st.write("### Monthly Breakdown")
|
|
st.dataframe(monthly_counts.rename("Days Worked"))
|
|
|
|
else:
|
|
st.info("No work days logged yet. Click dates on the calendar.")
|
|
|
|
# --- Debugging (Optional) ---
|
|
# with st.expander("Raw Data"):
|
|
# st.dataframe(df)
|