Initial commit
This commit is contained in:
commit
d976d12267
863 changed files with 138686 additions and 0 deletions
88
app.py
Normal file
88
app.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue