|
import datetime |
|
from typing import Dict, List, Any, Union, Optional |
|
import random |
|
import gradio as gr |
|
import json |
|
import matplotlib.pyplot as plt |
|
import numpy as np |
|
from collections import defaultdict |
|
|
|
|
|
from utils.storage import load_data, save_data, safe_get |
|
from utils.state import generate_id, get_timestamp, record_activity |
|
from utils.ai_models import generate_daily_plan, generate_motivational_quote |
|
from utils.ui_components import create_progress_ring, create_deadline_item, create_card, create_stat_card |
|
|
|
|
|
from utils.config import FILE_PATHS |
|
from utils.logging import setup_logger |
|
from utils.error_handling import handle_exceptions |
|
|
|
|
|
logger = setup_logger(__name__) |
|
|
|
|
|
SMART_CRITERIA = { |
|
"Specific": "Is your goal clearly defined and specific?", |
|
"Measurable": "Can you measure progress and know when it's achieved?", |
|
"Achievable": "Is this goal realistic and attainable?", |
|
"Relevant": "Does this goal align with your values and priorities?", |
|
"Time-bound": "Does your goal have a clear deadline?" |
|
} |
|
|
|
|
|
ACHIEVEMENT_BADGES = { |
|
"first_goal": {"name": "Goal Setter", "icon": "π―", "description": "Created your first goal"}, |
|
"goal_achiever": {"name": "Achiever", "icon": "π", "description": "Completed your first goal"}, |
|
"streak_master": {"name": "Streak Master", "icon": "π₯", "description": "Maintained a 7-day habit streak"}, |
|
"planner": {"name": "Master Planner", "icon": "π", "description": "Created 5 weekly plans"}, |
|
"reflector": {"name": "Reflective Mind", "icon": "π€", "description": "Completed 10 weekly reflections"}, |
|
"milestone_master": {"name": "Milestone Master", "icon": "π", "description": "Achieved 5 milestones"}, |
|
"habit_builder": {"name": "Habit Builder", "icon": "β‘", "description": "Created 10 habits"}, |
|
"analytics_pro": {"name": "Analytics Pro", "icon": "π", "description": "Viewed analytics 20 times"} |
|
} |
|
|
|
@handle_exceptions |
|
def initialize_goals_data(state: Dict[str, Any]) -> None: |
|
"""Initialize goals-related data structures""" |
|
if "goals" not in state: |
|
state["goals"] = [] |
|
if "habits" not in state: |
|
state["habits"] = [] |
|
if "milestones" not in state: |
|
state["milestones"] = [] |
|
if "weekly_plans" not in state: |
|
state["weekly_plans"] = [] |
|
if "monthly_plans" not in state: |
|
state["monthly_plans"] = [] |
|
if "reflections" not in state: |
|
state["reflections"] = [] |
|
if "achievements" not in state: |
|
state["achievements"] = [] |
|
if "goal_analytics" not in state: |
|
state["goal_analytics"] = {"views": 0, "goals_created": 0, "goals_completed": 0} |
|
|
|
@handle_exceptions |
|
def create_smart_goal_form() -> tuple: |
|
"""Create SMART goal creation form""" |
|
with gr.Group() as smart_form: |
|
gr.Markdown("### π― Create SMART Goal") |
|
|
|
goal_title = gr.Textbox(label="Goal Title", placeholder="Enter a clear, specific goal title") |
|
goal_description = gr.Textbox(label="Description", lines=3, placeholder="Describe your goal in detail") |
|
|
|
|
|
gr.Markdown("#### SMART Criteria Check") |
|
smart_checks = {} |
|
for criterion, question in SMART_CRITERIA.items(): |
|
smart_checks[criterion] = gr.Checkbox(label=f"{criterion}: {question}") |
|
|
|
|
|
with gr.Row(): |
|
goal_category = gr.Dropdown( |
|
choices=["Personal", "Professional", "Health", "Learning", "Financial", "Relationships", "Other"], |
|
label="Category", |
|
value="Personal" |
|
) |
|
goal_priority = gr.Dropdown( |
|
choices=["High", "Medium", "Low"], |
|
label="Priority", |
|
value="Medium" |
|
) |
|
|
|
with gr.Row(): |
|
start_date = gr.Textbox( |
|
label="Start Date", |
|
value=datetime.datetime.now().strftime("%Y-%m-%d") |
|
) |
|
target_date = gr.Textbox( |
|
label="Target Date", |
|
placeholder="YYYY-MM-DD" |
|
) |
|
|
|
|
|
gr.Markdown("#### Milestones") |
|
milestone_input = gr.Textbox( |
|
label="Add Milestone", |
|
placeholder="Enter milestone description" |
|
) |
|
milestones_list = gr.Textbox( |
|
label="Milestones", |
|
lines=3, |
|
placeholder="Milestones will appear here...", |
|
interactive=False |
|
) |
|
add_milestone_btn = gr.Button("Add Milestone", size="sm") |
|
|
|
|
|
success_metrics = gr.Textbox( |
|
label="Success Metrics", |
|
lines=2, |
|
placeholder="How will you measure success?" |
|
) |
|
|
|
create_goal_btn = gr.Button("Create SMART Goal", variant="primary") |
|
|
|
return (smart_form, goal_title, goal_description, smart_checks, goal_category, |
|
goal_priority, start_date, target_date, milestone_input, milestones_list, |
|
add_milestone_btn, success_metrics, create_goal_btn) |
|
|
|
@handle_exceptions |
|
def create_habit_tracker() -> tuple: |
|
"""Create habit tracking interface""" |
|
with gr.Group() as habit_tracker: |
|
gr.Markdown("### π Habit Tracker") |
|
|
|
|
|
with gr.Row(): |
|
habit_name = gr.Textbox(label="Habit Name", placeholder="e.g., Drink 8 glasses of water") |
|
habit_frequency = gr.Dropdown( |
|
choices=["Daily", "Weekly", "Monthly"], |
|
label="Frequency", |
|
value="Daily" |
|
) |
|
habit_target = gr.Number(label="Target (days)", value=21, minimum=1) |
|
|
|
add_habit_btn = gr.Button("Add Habit", variant="primary") |
|
|
|
|
|
habits_display = gr.Dataframe( |
|
headers=["Habit", "Current Streak", "Best Streak", "Target", "Progress %", "Actions"], |
|
datatype=["str", "number", "number", "number", "number", "str"], |
|
label="Your Habits" |
|
) |
|
|
|
|
|
gr.Markdown("#### Habit Calendar") |
|
habit_calendar = gr.HTML("<div id='habit-calendar'>Calendar will load here</div>") |
|
|
|
|
|
gr.Markdown("#### Quick Check-in") |
|
with gr.Row(): |
|
checkin_habit = gr.Dropdown(label="Select Habit", choices=[]) |
|
checkin_btn = gr.Button("Mark Complete", variant="secondary") |
|
|
|
return (habit_tracker, habit_name, habit_frequency, habit_target, add_habit_btn, |
|
habits_display, habit_calendar, checkin_habit, checkin_btn) |
|
|
|
@handle_exceptions |
|
def create_planning_tools() -> tuple: |
|
"""Create planning and scheduling tools""" |
|
with gr.Group() as planning_tools: |
|
gr.Markdown("### π
Planning & Time Blocking") |
|
|
|
with gr.Tabs(): |
|
|
|
with gr.TabItem("Daily Planning"): |
|
plan_date = gr.Textbox( |
|
label="Date", |
|
value=datetime.datetime.now().strftime("%Y-%m-%d") |
|
) |
|
|
|
|
|
gr.Markdown("#### π€ AI Suggestions") |
|
ai_suggestions = gr.Markdown("*Click 'Generate Suggestions' for AI-powered daily plan*") |
|
generate_suggestions_btn = gr.Button("Generate Suggestions") |
|
|
|
|
|
gr.Markdown("#### β° Time Blocks") |
|
with gr.Row(): |
|
block_time = gr.Textbox(label="Time", placeholder="09:00-10:00") |
|
block_activity = gr.Textbox(label="Activity", placeholder="Deep work on project X") |
|
block_priority = gr.Dropdown( |
|
choices=["High", "Medium", "Low"], |
|
label="Priority", |
|
value="Medium" |
|
) |
|
add_block_btn = gr.Button("Add Time Block") |
|
|
|
time_blocks_display = gr.Dataframe( |
|
headers=["Time", "Activity", "Priority", "Status"], |
|
datatype=["str", "str", "str", "str"], |
|
label="Today's Schedule" |
|
) |
|
|
|
|
|
with gr.TabItem("Weekly Planning"): |
|
week_start = gr.Textbox( |
|
label="Week Starting", |
|
value=datetime.datetime.now().strftime("%Y-%m-%d") |
|
) |
|
|
|
weekly_focus = gr.Textbox( |
|
label="Weekly Focus Areas", |
|
lines=3, |
|
placeholder="What are your main priorities this week?" |
|
) |
|
|
|
weekly_goals_checklist = gr.CheckboxGroup( |
|
label="Weekly Goals", |
|
choices=[] |
|
) |
|
|
|
save_weekly_plan_btn = gr.Button("Save Weekly Plan") |
|
|
|
|
|
with gr.TabItem("Monthly Planning"): |
|
month_year = gr.Textbox( |
|
label="Month/Year", |
|
value=datetime.datetime.now().strftime("%B %Y") |
|
) |
|
|
|
monthly_theme = gr.Textbox( |
|
label="Monthly Theme", |
|
placeholder="What's the main theme for this month?" |
|
) |
|
|
|
monthly_objectives = gr.Textbox( |
|
label="Key Objectives", |
|
lines=5, |
|
placeholder="List your main objectives for the month" |
|
) |
|
|
|
save_monthly_plan_btn = gr.Button("Save Monthly Plan") |
|
|
|
return (planning_tools, plan_date, ai_suggestions, generate_suggestions_btn, |
|
block_time, block_activity, block_priority, add_block_btn, time_blocks_display, |
|
week_start, weekly_focus, weekly_goals_checklist, save_weekly_plan_btn, |
|
month_year, monthly_theme, monthly_objectives, save_monthly_plan_btn) |
|
|
|
@handle_exceptions |
|
def create_reflection_journal() -> tuple: |
|
"""Create reflection and review system""" |
|
with gr.Group() as reflection_journal: |
|
gr.Markdown("### π€ Reflection Journal") |
|
|
|
with gr.Tabs(): |
|
|
|
with gr.TabItem("Weekly Reflection"): |
|
reflection_week = gr.Textbox( |
|
label="Week of", |
|
value=datetime.datetime.now().strftime("%Y-%m-%d") |
|
) |
|
|
|
|
|
gr.Markdown("#### Reflection Prompts") |
|
|
|
wins = gr.Textbox( |
|
label="π What were your biggest wins this week?", |
|
lines=3 |
|
) |
|
|
|
challenges = gr.Textbox( |
|
label="β οΈ What challenges did you face?", |
|
lines=3 |
|
) |
|
|
|
lessons = gr.Textbox( |
|
label="π What did you learn?", |
|
lines=3 |
|
) |
|
|
|
improvements = gr.Textbox( |
|
label="π What would you do differently?", |
|
lines=3 |
|
) |
|
|
|
next_week_focus = gr.Textbox( |
|
label="π― What will you focus on next week?", |
|
lines=3 |
|
) |
|
|
|
gratitude = gr.Textbox( |
|
label="π What are you grateful for?", |
|
lines=2 |
|
) |
|
|
|
save_reflection_btn = gr.Button("Save Reflection", variant="primary") |
|
|
|
|
|
with gr.TabItem("Monthly Review"): |
|
review_month = gr.Textbox( |
|
label="Month/Year", |
|
value=datetime.datetime.now().strftime("%B %Y") |
|
) |
|
|
|
monthly_achievements = gr.Textbox( |
|
label="π Major Achievements", |
|
lines=4 |
|
) |
|
|
|
goals_progress = gr.Textbox( |
|
label="π Goals Progress Review", |
|
lines=4 |
|
) |
|
|
|
habits_review = gr.Textbox( |
|
label="π Habits Review", |
|
lines=3 |
|
) |
|
|
|
next_month_goals = gr.Textbox( |
|
label="π― Next Month's Goals", |
|
lines=4 |
|
) |
|
|
|
save_monthly_review_btn = gr.Button("Save Monthly Review", variant="primary") |
|
|
|
|
|
gr.Markdown("#### Past Reflections") |
|
reflections_history = gr.Dataframe( |
|
headers=["Date", "Type", "Key Insights"], |
|
datatype=["str", "str", "str"], |
|
label="Reflection History" |
|
) |
|
|
|
return (reflection_journal, reflection_week, wins, challenges, lessons, improvements, |
|
next_week_focus, gratitude, save_reflection_btn, review_month, monthly_achievements, |
|
goals_progress, habits_review, next_month_goals, save_monthly_review_btn, |
|
reflections_history) |
|
|
|
@handle_exceptions |
|
def create_achievement_system() -> tuple: |
|
"""Create achievement badges and gamification""" |
|
with gr.Group() as achievement_system: |
|
gr.Markdown("### π Achievements & Badges") |
|
|
|
|
|
achievement_stats = gr.HTML(""" |
|
<div class="achievement-stats"> |
|
<div class="stat-item"> |
|
<span class="stat-number">0</span> |
|
<span class="stat-label">Badges Earned</span> |
|
</div> |
|
<div class="stat-item"> |
|
<span class="stat-number">0</span> |
|
<span class="stat-label">Goals Completed</span> |
|
</div> |
|
<div class="stat-item"> |
|
<span class="stat-number">0</span> |
|
<span class="stat-label">Streak Days</span> |
|
</div> |
|
</div> |
|
""") |
|
|
|
|
|
badges_display = gr.HTML("<div id='badges-grid'>Badges will load here</div>") |
|
|
|
|
|
gr.Markdown("#### Next Badge Progress") |
|
next_badge_progress = gr.HTML("<div id='next-badge'>Progress will load here</div>") |
|
|
|
return achievement_system, achievement_stats, badges_display, next_badge_progress |
|
|
|
@handle_exceptions |
|
def create_goal_analytics() -> tuple: |
|
"""Create analytics and insights dashboard""" |
|
with gr.Group() as analytics_dashboard: |
|
gr.Markdown("### π Goal Analytics & Insights") |
|
|
|
with gr.Tabs(): |
|
|
|
with gr.TabItem("Progress Charts"): |
|
|
|
completion_chart = gr.Plot(label="Goal Completion Rate") |
|
|
|
|
|
habit_chart = gr.Plot(label="Habit Consistency") |
|
|
|
|
|
category_chart = gr.Plot(label="Goals by Category") |
|
|
|
|
|
with gr.TabItem("Success Patterns"): |
|
success_insights = gr.Markdown("*Analytics will appear here*") |
|
|
|
|
|
performance_analysis = gr.Dataframe( |
|
headers=["Category", "Success Rate", "Avg. Completion Time", "Insights"], |
|
datatype=["str", "str", "str", "str"], |
|
label="Performance Analysis" |
|
) |
|
|
|
|
|
with gr.TabItem("Time Analysis"): |
|
time_insights = gr.Plot(label="Goal Completion Timeline") |
|
|
|
productivity_patterns = gr.Markdown("*Productivity patterns will appear here*") |
|
|
|
|
|
gr.Markdown("#### π€ AI-Powered Insights") |
|
ai_insights = gr.Markdown("*AI insights will be generated based on your data*") |
|
generate_insights_btn = gr.Button("Generate AI Insights") |
|
|
|
return (analytics_dashboard, completion_chart, habit_chart, category_chart, |
|
success_insights, performance_analysis, time_insights, productivity_patterns, |
|
ai_insights, generate_insights_btn) |
|
|
|
@handle_exceptions |
|
def create_goals_page(state: Dict[str, Any]) -> None: |
|
""" |
|
Create the comprehensive goals and planning page |
|
|
|
Args: |
|
state: Application state |
|
""" |
|
logger.info("Creating comprehensive goals page") |
|
|
|
|
|
initialize_goals_data(state) |
|
|
|
|
|
with gr.Column(elem_id="goals-page"): |
|
gr.Markdown("# π― Goals & Planning System") |
|
gr.Markdown("*Comprehensive goal management with SMART framework, habit tracking, and AI insights*") |
|
|
|
|
|
with gr.Row(): |
|
goals_stats = gr.HTML(""" |
|
<div class="stats-overview"> |
|
<div class="stat-card"> |
|
<h3>π Active Goals</h3> |
|
<p class="stat-number">0</p> |
|
</div> |
|
<div class="stat-card"> |
|
<h3>π₯ Habit Streaks</h3> |
|
<p class="stat-number">0</p> |
|
</div> |
|
<div class="stat-card"> |
|
<h3>π Completed</h3> |
|
<p class="stat-number">0</p> |
|
</div> |
|
<div class="stat-card"> |
|
<h3>π Success Rate</h3> |
|
<p class="stat-number">0%</p> |
|
</div> |
|
</div> |
|
""") |
|
|
|
|
|
with gr.Tabs(elem_id="goals-main-tabs"): |
|
|
|
with gr.TabItem("π― SMART Goals", elem_id="smart-goals-tab"): |
|
smart_form, goal_title, goal_description, smart_checks, goal_category, goal_priority, start_date, target_date, milestone_input, milestones_list, add_milestone_btn, success_metrics, create_goal_btn = create_smart_goal_form() |
|
|
|
|
|
gr.Markdown("### Current Goals") |
|
goals_display = gr.Dataframe( |
|
headers=["Title", "Category", "Priority", "Progress", "Target Date", "Status"], |
|
datatype=["str", "str", "str", "str", "str", "str"], |
|
label="Your Goals" |
|
) |
|
|
|
|
|
with gr.TabItem("π Habit Tracker", elem_id="habits-tab"): |
|
habit_tracker, habit_name, habit_frequency, habit_target, add_habit_btn, habits_display, habit_calendar, checkin_habit, checkin_btn = create_habit_tracker() |
|
|
|
|
|
with gr.TabItem("π
Planning", elem_id="planning-tab"): |
|
planning_tools, plan_date, ai_suggestions, generate_suggestions_btn, block_time, block_activity, block_priority, add_block_btn, time_blocks_display, week_start, weekly_focus, weekly_goals_checklist, save_weekly_plan_btn, month_year, monthly_theme, monthly_objectives, save_monthly_plan_btn = create_planning_tools() |
|
|
|
|
|
with gr.TabItem("π€ Reflection", elem_id="reflection-tab"): |
|
reflection_journal, reflection_week, wins, challenges, lessons, improvements, next_week_focus, gratitude, save_reflection_btn, review_month, monthly_achievements, goals_progress, habits_review, next_month_goals, save_monthly_review_btn, reflections_history = create_reflection_journal() |
|
|
|
|
|
with gr.TabItem("π Achievements", elem_id="achievements-tab"): |
|
achievement_system, achievement_stats, badges_display, next_badge_progress = create_achievement_system() |
|
|
|
|
|
with gr.TabItem("π Analytics", elem_id="analytics-tab"): |
|
analytics_dashboard, completion_chart, habit_chart, category_chart, success_insights, performance_analysis, time_insights, productivity_patterns, ai_insights, generate_insights_btn = create_goal_analytics() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
habit_calendar = gr.HTML( |
|
|
|
"<div class='habit-calendar-placeholder'>Select a habit to view calendar</div>" |
|
) |
|
|
|
|
|
habit_details = gr.Markdown( |
|
"*Select a habit to see details*" |
|
) |
|
|
|
|
|
with gr.Row(): |
|
check_in_btn = gr.Button("β
Check In Today") |
|
reset_habit_btn = gr.Button("π Reset Habit") |
|
|
|
|
|
with gr.Group(elem_id="goal-detail-modal", visible=False) as goal_detail_modal: |
|
gr.Markdown("## Goal Details") |
|
|
|
|
|
goal_title_display = gr.Textbox(label="Title", interactive=True) |
|
goal_description_display = gr.Textbox(label="Description", lines=3, interactive=True) |
|
goal_status_display = gr.Dropdown( |
|
choices=["Not Started", "In Progress", "Completed"], |
|
label="Status", |
|
interactive=True |
|
) |
|
goal_priority_display = gr.Dropdown( |
|
choices=["High", "Medium", "Low"], |
|
label="Priority", |
|
interactive=True |
|
) |
|
goal_deadline_display = gr.Textbox( |
|
label="Deadline (YYYY-MM-DD)", |
|
interactive=True |
|
) |
|
|
|
|
|
goal_progress_display = gr.Slider( |
|
minimum=0, |
|
maximum=100, |
|
value=0, |
|
step=5, |
|
label="Progress (%)" |
|
) |
|
|
|
|
|
with gr.Row(): |
|
save_goal_btn = gr.Button("Save Changes") |
|
delete_goal_btn = gr.Button("Delete Goal") |
|
close_detail_btn = gr.Button("Close") |
|
|
|
|
|
with gr.Group(): |
|
gr.Markdown("### Related Tasks") |
|
related_tasks = gr.Dataframe( |
|
headers=["Task", "Status"], |
|
datatype=["str", "str"], |
|
col_count=(2, "fixed"), |
|
row_count=(0, "dynamic"), |
|
elem_id="related-tasks-list" |
|
) |
|
link_task_btn = gr.Button("Link Task") |
|
|
|
|
|
with gr.Group(elem_id="add-goal-modal", visible=False) as add_goal_modal: |
|
gr.Markdown("## Add New Goal") |
|
|
|
|
|
new_goal_title = gr.Textbox(label="Title", placeholder="Enter goal title") |
|
new_goal_description = gr.Textbox( |
|
label="Description", |
|
placeholder="Enter goal description", |
|
lines=3 |
|
) |
|
new_goal_status = gr.Dropdown( |
|
choices=["Not Started", "In Progress", "Completed"], |
|
label="Status", |
|
value="Not Started" |
|
) |
|
new_goal_priority = gr.Dropdown( |
|
choices=["High", "Medium", "Low"], |
|
label="Priority", |
|
value="Medium" |
|
) |
|
new_goal_deadline = gr.Textbox( |
|
label="Deadline (YYYY-MM-DD)", |
|
placeholder="YYYY-MM-DD" |
|
) |
|
|
|
|
|
with gr.Accordion("Goal Details", open=False): |
|
gr.Markdown("### π·οΈ Category") |
|
new_goal_category = gr.Dropdown( |
|
choices=["Personal", "Professional", "Health", "Financial", "Learning", "Other"], |
|
label="Category", |
|
value="Personal" |
|
) |
|
|
|
gr.Markdown("### π Measurability") |
|
new_goal_measurable = gr.Checkbox( |
|
label="Is this goal measurable?", |
|
value=True |
|
) |
|
new_goal_target = gr.Number( |
|
label="Target Value", |
|
value=100 |
|
) |
|
new_goal_unit = gr.Textbox( |
|
label="Unit", |
|
placeholder="e.g., kg, books, hours" |
|
) |
|
|
|
|
|
with gr.Row(): |
|
create_goal_btn = gr.Button("Create Goal") |
|
cancel_add_btn = gr.Button("Cancel") |
|
|
|
|
|
@handle_exceptions |
|
def render_goals(view): |
|
"""Render goals based on the selected view""" |
|
logger.debug(f"Rendering goals with view: {view}") |
|
goals = safe_get(state, "goals", []) |
|
|
|
|
|
if view == "Active Goals": |
|
filtered_goals = [g for g in goals if g.get("status", "") != "Completed"] |
|
elif view == "Completed Goals": |
|
filtered_goals = [g for g in goals if g.get("status", "") == "Completed"] |
|
else: |
|
filtered_goals = goals |
|
|
|
|
|
priority_order = {"High": 0, "Medium": 1, "Low": 2} |
|
filtered_goals.sort(key=lambda x: ( |
|
priority_order.get(x.get("priority", "Medium"), 1), |
|
x.get("deadline", "9999-12-31") |
|
)) |
|
|
|
|
|
goal_cards = [] |
|
for goal in filtered_goals: |
|
|
|
title = safe_get(goal, "title", "Untitled Goal") |
|
description = safe_get(goal, "description", "") |
|
status = safe_get(goal, "status", "Not Started") |
|
priority = safe_get(goal, "priority", "Medium") |
|
progress = safe_get(goal, "progress", 0) |
|
|
|
|
|
deadline_str = "No deadline" |
|
if "deadline" in goal: |
|
try: |
|
deadline = datetime.datetime.fromisoformat(goal["deadline"]) |
|
deadline_str = deadline.strftime("%b %d, %Y") |
|
except: |
|
logger.warning(f"Failed to parse deadline for goal: {goal.get('id', 'unknown')}") |
|
|
|
|
|
status_emoji = "π΄" if status == "Not Started" else \ |
|
"π‘" if status == "In Progress" else "π’" |
|
|
|
|
|
priority_color = "red" if priority == "High" else \ |
|
"orange" if priority == "Medium" else "green" |
|
|
|
|
|
card_html = f""" |
|
<div class="goal-card priority-{priority.lower()}" data-goal-id="{goal.get('id', '')}"> |
|
<div class="goal-header"> |
|
<h3>{title}</h3> |
|
<span class="goal-status">{status_emoji} {status}</span> |
|
</div> |
|
<div class="goal-description">{description}</div> |
|
<div class="goal-progress"> |
|
<div class="progress-bar"> |
|
<div class="progress-fill" style="width: {progress}%;"></div> |
|
</div> |
|
<span class="progress-text">{progress}%</span> |
|
</div> |
|
<div class="goal-footer"> |
|
<span class="goal-deadline">π
{deadline_str}</span> |
|
<span class="goal-priority" style="color: {priority_color};">β‘ {priority}</span> |
|
</div> |
|
</div> |
|
""" |
|
|
|
goal_cards.append(card_html) |
|
|
|
|
|
if goal_cards: |
|
return "\n".join(goal_cards) |
|
else: |
|
return "<div class='no-goals-message'>No goals found. Click 'β Add Goal' to create one.</div>" |
|
|
|
|
|
view_selector.change( |
|
render_goals, |
|
inputs=[view_selector], |
|
outputs=[goals_container] |
|
) |
|
|
|
|
|
@handle_exceptions |
|
def show_add_goal_modal(): |
|
"""Show the add goal modal""" |
|
logger.debug("Showing add goal modal") |
|
return gr.update(visible=True) |
|
|
|
|
|
@handle_exceptions |
|
def hide_add_goal_modal(): |
|
"""Hide the add goal modal""" |
|
logger.debug("Hiding add goal modal") |
|
return gr.update(visible=False) |
|
|
|
|
|
add_goal_btn.click(show_add_goal_modal, inputs=[], outputs=[add_goal_modal]) |
|
cancel_add_btn.click(hide_add_goal_modal, inputs=[], outputs=[add_goal_modal]) |
|
|
|
|
|
@handle_exceptions |
|
def create_goal(title, description, status, priority, deadline, |
|
category, is_measurable, target, unit): |
|
"""Create a new goal""" |
|
logger.debug("Creating new goal") |
|
if not title.strip(): |
|
logger.warning("Attempted to create goal without title") |
|
return "Please enter a goal title", gr.update(visible=True) |
|
|
|
|
|
deadline_iso = None |
|
if deadline.strip(): |
|
try: |
|
deadline_date = datetime.datetime.strptime(deadline.strip(), "%Y-%m-%d") |
|
deadline_iso = deadline_date.isoformat() |
|
except ValueError: |
|
logger.warning(f"Invalid date format for deadline: {deadline}") |
|
return "Invalid date format. Use YYYY-MM-DD", gr.update(visible=True) |
|
|
|
|
|
new_goal = { |
|
"id": generate_id(), |
|
"title": title.strip(), |
|
"description": description.strip(), |
|
"status": status, |
|
"priority": priority, |
|
"progress": 0, |
|
"category": category, |
|
"created_at": get_timestamp() |
|
} |
|
|
|
if deadline_iso: |
|
new_goal["deadline"] = deadline_iso |
|
|
|
|
|
if is_measurable: |
|
new_goal["measurable"] = True |
|
new_goal["target"] = float(target) if target else 100 |
|
new_goal["current"] = 0 |
|
if unit.strip(): |
|
new_goal["unit"] = unit.strip() |
|
|
|
|
|
if "goals" not in state: |
|
state["goals"] = [] |
|
state["goals"].append(new_goal) |
|
|
|
|
|
if "stats" not in state: |
|
state["stats"] = {} |
|
if "goals_total" not in state["stats"]: |
|
state["stats"]["goals_total"] = 0 |
|
state["stats"]["goals_total"] += 1 |
|
|
|
|
|
record_activity(state, { |
|
"type": "goal_created", |
|
"title": title, |
|
"timestamp": get_timestamp() |
|
}) |
|
|
|
|
|
save_data(FILE_PATHS["goals"], state["goals"]) |
|
|
|
|
|
goals_html = render_goals(view_selector.value) |
|
|
|
|
|
return "Goal created successfully!", gr.update(visible=False), goals_html |
|
|
|
|
|
create_goal_btn.click( |
|
create_goal, |
|
inputs=[ |
|
new_goal_title, new_goal_description, new_goal_status, |
|
new_goal_priority, new_goal_deadline, new_goal_category, |
|
new_goal_measurable, new_goal_target, new_goal_unit |
|
], |
|
outputs=[gr.Markdown(visible=False), add_goal_modal, goals_container] |
|
) |
|
|
|
|
|
@handle_exceptions |
|
def generate_plan(): |
|
"""Generate a daily plan using AI""" |
|
logger.debug("Generating daily plan") |
|
tasks = safe_get(state, "tasks", []) |
|
goals = safe_get(state, "goals", []) |
|
|
|
|
|
active_tasks = [t for t in tasks if t.get("status", "") != "done"] |
|
active_goals = [g for g in goals if g.get("status", "") != "Completed"] |
|
|
|
|
|
plan = generate_daily_plan(active_tasks, active_goals) |
|
|
|
return plan |
|
|
|
|
|
generate_plan_btn.click( |
|
generate_plan, |
|
inputs=[], |
|
outputs=[daily_plan] |
|
) |
|
|
|
|
|
@handle_exceptions |
|
def save_manual_plan(date, plan): |
|
"""Save a manual daily plan""" |
|
logger.debug(f"Saving manual plan for date: {date}") |
|
if not plan.strip(): |
|
logger.warning("Attempted to save empty plan") |
|
return "Please enter a plan" |
|
|
|
|
|
if "plans" not in state: |
|
state["plans"] = {} |
|
|
|
state["plans"][date] = { |
|
"content": plan.strip(), |
|
"created_at": get_timestamp() |
|
} |
|
|
|
|
|
save_data(FILE_PATHS["plans"], state["plans"]) |
|
|
|
|
|
record_activity(state, { |
|
"type": "plan_created", |
|
"title": f"Plan for {date}", |
|
"timestamp": get_timestamp() |
|
}) |
|
|
|
return "Plan saved successfully!" |
|
|
|
|
|
save_plan_btn.click( |
|
save_manual_plan, |
|
inputs=[plan_date, manual_plan], |
|
outputs=[gr.Markdown(visible=False)] |
|
) |
|
|
|
|
|
@handle_exceptions |
|
def get_motivational_quote(): |
|
"""Get a motivational quote using AI""" |
|
logger.debug("Generating motivational quote") |
|
quote = generate_motivational_quote() |
|
return f"*\"{quote}\"*" |
|
|
|
|
|
new_quote_btn.click( |
|
get_motivational_quote, |
|
inputs=[], |
|
outputs=[motivation_quote] |
|
) |
|
|
|
|
|
@handle_exceptions |
|
def add_habit(name, target): |
|
"""Add a new habit to track""" |
|
logger.debug(f"Adding new habit: {name}") |
|
if not name.strip(): |
|
logger.warning("Attempted to add habit without name") |
|
return "Please enter a habit name" |
|
|
|
|
|
new_habit = { |
|
"id": generate_id(), |
|
"name": name.strip(), |
|
"target": int(target), |
|
"streak": 0, |
|
"history": {}, |
|
"created_at": get_timestamp() |
|
} |
|
|
|
|
|
if "habits" not in state: |
|
state["habits"] = [] |
|
state["habits"].append(new_habit) |
|
|
|
|
|
save_data(FILE_PATHS["habits"], state["habits"]) |
|
|
|
|
|
record_activity(state, { |
|
"type": "habit_created", |
|
"title": name, |
|
"timestamp": get_timestamp() |
|
}) |
|
|
|
|
|
habits_data = [] |
|
for habit in safe_get(state, "habits", []): |
|
habits_data.append([ |
|
safe_get(habit, "name", "Unnamed Habit"), |
|
safe_get(habit, "streak", 0), |
|
safe_get(habit, "target", 21) |
|
]) |
|
|
|
return "Habit added successfully!", habits_data |
|
|
|
|
|
add_habit_btn.click( |
|
add_habit, |
|
inputs=[new_habit_name, new_habit_target], |
|
outputs=[gr.Markdown(visible=False), habits_list] |
|
) |
|
|
|
|
|
goals_container.value = render_goals("Active Goals") |
|
|
|
|
|
motivation_quote.value = get_motivational_quote() |
|
|
|
|
|
habits_data = [] |
|
for habit in safe_get(state, "habits", []): |
|
habits_data.append([ |
|
safe_get(habit, "name", "Unnamed Habit"), |
|
safe_get(habit, "streak", 0), |
|
safe_get(habit, "target", 21) |
|
]) |
|
habits_list.value = habits_data |