""" Schedule & Note Management Web App A lightweight Gradio 6 application for managing tasks, events, reminders, and fees. Based on Product Requirements Document v1.0 """ import gradio as gr import json from datetime import datetime, timedelta from typing import Optional from enum import Enum # ============================================================================ # DATA MODELS AND STATE MANAGEMENT # ============================================================================ class TaskPriority(str, Enum): LOW = "Low" MEDIUM = "Medium" HIGH = "High" class TaskStatus(str, Enum): PENDING = "Pending" COMPLETED = "Completed" class ReminderType(str, Enum): NONE = "None" BEFORE_15_MIN = "15 minutes before" BEFORE_30_MIN = "30 minutes before" BEFORE_1_HOUR = "1 hour before" BEFORE_1_DAY = "1 day before" # Sample data for demonstration SAMPLE_TASKS = [ { "id": "1", "title": "Team Meeting", "description": "Weekly sync with the development team", "date": datetime.now().strftime("%Y-%m-%d"), "time": "09:00", "priority": TaskPriority.HIGH.value, "status": TaskStatus.PENDING.value, "fee": 0.0, "reminder": ReminderType.BEFORE_15_MIN.value, "notes": "Prepare agenda beforehand", "created_at": datetime.now().isoformat() }, { "id": "2", "title": "Client Presentation", "description": "Present the new product roadmap", "date": datetime.now().strftime("%Y-%m-%d"), "time": "14:00", "priority": TaskPriority.HIGH.value, "status": TaskStatus.PENDING.value, "fee": 150.0, "reminder": ReminderType.BEFORE_1_HOUR.value, "notes": "Review slides and prepare demo", "created_at": datetime.now().isoformat() }, { "id": "3", "title": "Code Review", "description": "Review PRs for the new feature branch", "date": (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d"), "time": "11:00", "priority": TaskPriority.MEDIUM.value, "status": TaskStatus.PENDING.value, "fee": 0.0, "reminder": ReminderType.BEFORE_30_MIN.value, "notes": "Check for security vulnerabilities", "created_at": datetime.now().isoformat() }, { "id": "4", "title": "Gym Session", "description": "Weekly workout routine", "date": datetime.now().strftime("%Y-%m-%d"), "time": "18:00", "priority": TaskPriority.LOW.value, "status": TaskStatus.COMPLETED.value, "fee": 50.0, "reminder": ReminderType.NONE.value, "notes": "Focus on cardio today", "created_at": datetime.now().isoformat() } ] def get_next_id(tasks: list) -> str: """Generate a new unique ID for tasks.""" if not tasks: return "1" max_id = max(int(task["id"]) for task in tasks) return str(max_id + 1) def calculate_weekly_stats(tasks: list) -> dict: """Calculate statistics for the current week.""" now = datetime.now() week_start = now - timedelta(days=now.weekday()) week_end = week_start + timedelta(days=6) weekly_tasks = [ t for t in tasks if week_start.strftime("%Y-%m-%d") <= t["date"] <= week_end.strftime("%Y-%m-%d") ] completed = sum(1 for t in weekly_tasks if t["status"] == TaskStatus.COMPLETED.value) total_fee = sum(float(t.get("fee", 0) or 0) for t in weekly_tasks) return { "total_tasks": len(weekly_tasks), "completed": completed, "pending": len(weekly_tasks) - completed, "total_fee": total_fee, "completion_rate": round((completed / len(weekly_tasks) * 100), 1) if weekly_tasks else 0 } def get_weekly_schedule(tasks: list) -> str: """Generate a weekly schedule display.""" now = datetime.now() days = [] for i in range(7): day = now + timedelta(days=i) day_str = day.strftime("%Y-%m-%d") day_name = day.strftime("%A") is_today = i == 0 day_tasks = [ f" • **{t['time']}** - {t['title']}" for t in sorted(tasks, key=lambda x: x.get("time", "")) if t["date"] == day_str ] day_header = f"**{day_name} {day.strftime('%b %d')}" + (' (Today)' if is_today else '') + "**" day_content = "\n".join(day_tasks) if day_tasks else " No tasks scheduled" days.append(f"{day_header}\n{day_content}") return "\n\n".join(days) # ============================================================================ # APPLICATION STATE # ============================================================================ class AppState: """Application state manager for Gradio 6.""" def __init__(self): self.tasks = SAMPLE_TASKS.copy() def get_tasks(self) -> list: """Get all tasks.""" return self.tasks def add_task(self, task: dict) -> None: """Add a new task.""" task["id"] = get_next_id(self.tasks) task["created_at"] = datetime.now().isoformat() self.tasks.append(task) def update_task(self, task_id: str, updates: dict) -> None: """Update an existing task.""" for task in self.tasks: if task["id"] == task_id: task.update(updates) break def delete_task(self, task_id: str) -> None: """Delete a task by ID.""" self.tasks = [t for t in self.tasks if t["id"] != task_id] def get_task_by_id(self, task_id: str) -> Optional[dict]: """Get a task by its ID.""" for task in self.tasks: if task["id"] == task_id: return task return None # Initialize global state app_state = AppState() # ============================================================================ # HELPER FUNCTIONS # ============================================================================ def refresh_task_list() -> dict: """Refresh the task list and return current state.""" tasks = app_state.get_tasks() return { task_list: create_task_cards(tasks), task_count: f"Total Tasks: {len(tasks)}", weekly_stats: create_weekly_stats_display(), weekly_schedule: get_weekly_schedule(tasks) } def create_task_cards(tasks: list) -> str: """Create HTML cards for task display.""" if not tasks: return """

šŸ“‹ No tasks yet

Create your first task to get started!

""" cards = [] sorted_tasks = sorted(tasks, key=lambda x: (x.get("date", ""), x.get("time", ""))) for task in sorted_tasks: priority_colors = { "Low": "#28a745", "Medium": "#ffc107", "High": "#dc3545" } status_colors = { "Pending": "#6c757d", "Completed": "#28a745" } priority_color = priority_colors.get(task.get("priority", "Medium"), "#6c757d") status_color = status_colors.get(task.get("status", "Pending"), "#6c757d") card = f"""

{task['title']}

{task.get('priority', 'Medium')} {task.get('status', 'Pending')}
šŸ“… {task.get('date', 'No date')}
šŸ• {task.get('time', 'No time')}

{task.get('description', 'No description')}

{'šŸ’° Fee: $' + str(task.get('fee', 0)) if float(task.get('fee', 0)) > 0 else ''} {' | ā° Reminder: ' + task.get('reminder', 'None') if task.get('reminder') != 'None' else ''}
ID: {task['id']}
""" cards.append(card) return "\n".join(cards) def create_weekly_stats_display() -> str: """Create weekly statistics display.""" stats = calculate_weekly_stats(app_state.get_tasks()) return f"""
{stats['total_tasks']}
This Week's Tasks
{stats['completed']}
Completed
{stats['pending']}
Pending
${stats['total_fee']:.2f}
Total Fees
""" # ============================================================================ # TASK OPERATIONS # ============================================================================ def add_new_task( title: str, description: str, task_date: str, task_time: str, priority: str, fee: float, reminder: str, notes: str ) -> dict: """Add a new task to the system.""" if not title or not task_date or not task_time: return { task_list: create_task_cards(app_state.get_tasks()), status_msg: gr.update(value="āŒ Please fill in all required fields!", visible=True), form_message: gr.update(value="āŒ Error: Title, date, and time are required", visible=True) } new_task = { "title": title, "description": description, "date": task_date, "time": task_time, "priority": priority, "status": TaskStatus.PENDING.value, "fee": fee, "reminder": reminder, "notes": notes } app_state.add_task(new_task) return { task_list: create_task_cards(app_state.get_tasks()), status_msg: gr.update(value="āœ… Task created successfully!", visible=True), form_message: gr.update(value="āœ… Task added successfully!", visible=True), # Clear form title_input: gr.update(value=""), description_input: gr.update(value=""), fee_input: gr.update(value=0.0), notes_input: gr.update(value="") } def update_task_status(task_id: str, new_status: str) -> dict: """Update a task's status.""" if task_id and new_status: app_state.update_task(task_id, {"status": new_status}) return { task_list: create_task_cards(app_state.get_tasks()), status_msg: gr.update(value=f"āœ… Task {task_id} marked as {new_status}", visible=True) } def delete_task_action(task_id: str) -> dict: """Delete a task.""" if task_id: app_state.delete_task(task_id) return { task_list: create_task_cards(app_state.get_tasks()), status_msg: gr.update(value=f"āœ… Task deleted successfully", visible=True) } def load_task_for_edit(task_id: str) -> dict: """Load task data into the edit form.""" task = app_state.get_task_by_id(task_id) if task: return { edit_task_id: task_id, edit_title: gr.update(value=task["title"]), edit_description: gr.update(value=task.get("description", "")), edit_date: gr.update(value=task.get("date", "")), edit_time: gr.update(value=task.get("time", "")), edit_priority: gr.update(value=task.get("priority", "Medium")), edit_fee: gr.update(value=float(task.get("fee", 0) or 0)), edit_reminder: gr.update(value=task.get("reminder", "None")), edit_notes: gr.update(value=task.get("notes", "")), show_edit_form: gr.update(visible=True) } return {show_edit_form: gr.update(visible=False)} def save_edited_task( task_id: str, title: str, description: str, task_date: str, task_time: str, priority: str, fee: float, reminder: str, notes: str ) -> dict: """Save edited task.""" if task_id and title: updates = { "title": title, "description": description, "date": task_date, "time": task_time, "priority": priority, "fee": fee, "reminder": reminder, "notes": notes } app_state.update_task(task_id, updates) return { task_list: create_task_cards(app_state.get_tasks()), status_msg: gr.update(value="āœ… Task updated successfully!", visible=True), show_edit_form: gr.update(visible=False) } def filter_tasks(status_filter: str, priority_filter: str) -> dict: """Filter tasks by status and priority.""" tasks = app_state.get_tasks() if status_filter != "All": tasks = [t for t in tasks if t.get("status") == status_filter] if priority_filter != "All": tasks = [t for t in tasks if t.get("priority") == priority_filter] return { task_list: create_task_cards(tasks) } def search_tasks(search_query: str) -> dict: """Search tasks by title or description.""" if not search_query.strip(): return {task_list: create_task_cards(app_state.get_tasks())} query = search_query.lower() tasks = [ t for t in app_state.get_tasks() if query in t.get("title", "").lower() or query in t.get("description", "").lower() ] return { task_list: create_task_cards(tasks) } # ============================================================================ # GRADIO 6 APPLICATION # ============================================================================ # Custom theme for the application custom_theme = gr.themes.Soft( primary_hue="indigo", secondary_hue="purple", neutral_hue="slate", font=gr.themes.GoogleFont("Inter"), text_size="lg", spacing_size="lg", radius_size="md" ).set( button_primary_background_fill="*primary_600", button_primary_background_fill_hover="*primary_700", button_secondary_background_fill="*secondary_100", button_secondary_background_fill_hover="*secondary_200", block_title_text_weight="600", block_background_fill="white", block_radius="12px", ) with gr.Blocks(theme=custom_theme) as demo: # Header gr.HTML("""

šŸ“… Schedule & Note Management

Plan tasks, manage events, and track fees efficiently

""") gr.HTML("""
✨ Built with anycoder
""") # Main content with tabs with gr.Tabs() as tabs: # Tab 1: Dashboard with gr.TabItem("šŸ“Š Dashboard", id="dashboard"): gr.Markdown("### šŸ“Š Weekly Overview") with gr.Row(): with gr.Column(scale=2): weekly_stats_html = gr.HTML( value=create_weekly_stats_display(), elem_id="weekly-stats" ) with gr.Column(scale=1): gr.Markdown("### šŸ“… Quick Stats") task_count = gr.Markdown(f"**Total Tasks: {len(app_state.get_tasks())}**") gr.Markdown("### šŸ“† This Week's Schedule") weekly_schedule = gr.Markdown( value=get_weekly_schedule(app_state.get_tasks()), elem_id="weekly-schedule" ) status_msg = gr.Markdown(visible=False, value="") # Tab 2: Task Management with gr.TabItem("āœ… Tasks", id="tasks"): gr.Markdown("### āœ… Task Management") # Search and filter row with gr.Row(): with gr.Column(scale=3): search_input = gr.Textbox( label="šŸ” Search Tasks", placeholder="Search by title or description...", elem_id="search-input" ) with gr.Column(scale=1): status_filter = gr.Dropdown( choices=["All", "Pending", "Completed"], value="All", label="Status" ) with gr.Column(scale=1): priority_filter = gr.Dropdown( choices=["All", "Low", "Medium", "High"], value="All", label="Priority" ) # Task list display task_list = gr.HTML( value=create_task_cards(app_state.get_tasks()), elem_id="task-list" ) status_msg = gr.Markdown(visible=False, value="") # Tab 3: Add New Task with gr.TabItem("āž• Add Task", id="add-task"): gr.Markdown("### āž• Create New Task") with gr.Row(): with gr.Column(scale=2): title_input = gr.Textbox( label="Task Title *", placeholder="Enter task title", elem_id="title-input" ) description_input = gr.Textbox( label="Description", placeholder="Enter task description", lines=3, elem_id="description-input" ) with gr.Column(scale=1): task_date = gr.DateTime( label="Date & Time *", type="datetime", elem_id="task-date" ) task_time = gr.Textbox( label="Time (HH:MM) *", placeholder="09:00", value="09:00", elem_id="task-time" ) with gr.Row(): with gr.Column(): priority = gr.Radio( choices=["Low", "Medium", "High"], value="Medium", label="Priority" ) with gr.Column(): fee_input = gr.Number( label="Fee/Cost ($)", value=0.0, minimum=0.0, elem_id="fee-input" ) with gr.Column(): reminder = gr.Dropdown( choices=["None", "15 minutes before", "30 minutes before", "1 hour before", "1 day before"], value="None", label="Reminder" ) notes_input = gr.Textbox( label="Notes", placeholder="Additional notes or comments...", lines=2, elem_id="notes-input" ) form_message = gr.Markdown(visible=False, value="") with gr.Row(): add_btn = gr.Button("Create Task", variant="primary", size="lg") clear_btn = gr.Button("Clear Form", variant="secondary") # Tab 4: Edit Task with gr.TabItem("āœļø Edit Task", id="edit-task"): gr.Markdown("### āœļø Edit Task") # Task selection dropdown task_selector = gr.Dropdown( choices=[(f"{t['title']} ({t.get('date', 'No date')}) - ID:{t['id']}", t['id']) for t in app_state.get_tasks()], label="Select Task to Edit", allow_custom_value=True, elem_id="task-selector" ) show_edit_form = gr.Column(visible=False, elem_id="edit-form-container") with show_edit_form: edit_task_id = gr.Textbox(visible=False, elem_id="edit-task-id") with gr.Row(): with gr.Column(scale=2): edit_title = gr.Textbox( label="Task Title *", placeholder="Enter task title", elem_id="edit-title" ) edit_description = gr.Textbox( label="Description", placeholder="Enter task description", lines=3, elem_id="edit-description" ) with gr.Column(scale=1): edit_date = gr.Textbox( label="Date (YYYY-MM-DD) *", placeholder="2024-01-15", elem_id="edit-date" ) edit_time = gr.Textbox( label="Time (HH:MM) *", placeholder="09:00", elem_id="edit-time" ) with gr.Row(): with gr.Column(): edit_priority = gr.Radio( choices=["Low", "Medium", "High"], value="Medium", label="Priority" ) with gr.Column(): edit_fee = gr.Number( label="Fee/Cost ($)", value=0.0, minimum=0.0, elem_id="edit-fee" ) with gr.Column(): edit_reminder = gr.Dropdown( choices=["None", "15 minutes before", "30 minutes before", "1 hour before", "1 day before"], value="None", label="Reminder" ) edit_notes = gr.Textbox( label="Notes", placeholder="Additional notes or comments...", lines=2, elem_id="edit-notes" ) with gr.Row(): save_btn = gr.Button("Save Changes", variant="primary", size="lg") cancel_btn = gr.Button("Cancel", variant="secondary") # Tab 5: Notes Manager with gr.TabItem("šŸ“ Notes", id="notes"): gr.Markdown("### šŸ“ Quick Notes") gr.Markdown("*Notes are attached to individual tasks. View task notes in the Tasks tab.*") with gr.Row(): quick_note = gr.Textbox( label="Quick Note", placeholder="Write a quick note...", lines=4 ) note_display = gr.Markdown( value="**Recent Notes**\n\n• Review meeting notes from Monday\n• Update project timeline\n• Prepare budget report", elem_id="note-display" ) with gr.Row(): save_note_btn = gr.Button("Save Note", variant="primary") clear_note_btn = gr.Button("Clear", variant="secondary") # Tab 6: Fees Summary with gr.TabItem("šŸ’° Fees", id="fees"): gr.Markdown("### šŸ’° Fee Tracking Summary") # Fee statistics tasks = app_state.get_tasks() total_fees = sum(float(t.get("fee", 0) or 0) for t in tasks) task_with_fees = sum(1 for t in tasks if float(t.get("fee", 0) or 0) > 0) avg_fee = total_fees / task_with_fees if task_with_fees > 0 else 0 gr.HTML(f"""
${total_fees:.2f}
Total Fees
{task_with_fees}
Tasks with Fees
${avg_fee:.2f}
Average Fee
""") gr.Markdown("### šŸ’µ Tasks with Fees") fee_task_list = gr.HTML( value=create_task_cards([t for t in tasks if float(t.get("fee", 0) or 0) > 0]), elem_id="fee-task-list" ) # ============================================================================ # EVENT HANDLERS # ============================================================================ # Search and filter handlers search_input.submit(search_tasks, inputs=search_input, outputs=[task_list]) status_filter.change(filter_tasks, inputs=[status_filter, priority_filter], outputs=[task_list]) priority_filter.change(filter_tasks, inputs=[status_filter, priority_filter], outputs=[task_list]) # Add task handlers add_btn.click( add_new_task, inputs=[title_input, description_input, task_date, task_time, priority, fee_input, reminder, notes_input], outputs=[task_list, status_msg, form_message, title_input, description_input, fee_input, notes_input] ) clear_btn.click( lambda: { title_input: gr.update(value=""), description_input: gr.update(value=""), fee_input: gr.update(value=0.0), notes_input: gr.update(value=""), form_message: gr.update(visible=False) }, outputs=[title_input, description_input, fee_input, notes_input, form_message] ) # Task selector for editing task_selector.select( load_task_for_edit, inputs=task_selector, outputs=[edit_task_id, edit_title, edit_description, edit_date, edit_time, edit_priority, edit_fee, edit_reminder, edit_notes, show_edit_form] ) # Save edited task save_btn.click( save_edited_task, inputs=[edit_task_id, edit_title, edit_description, edit_date, edit_time, edit_priority, edit_fee, edit_reminder, edit_notes], outputs=[task_list, status_msg, show_edit_form] ) # Cancel edit cancel_btn.click( lambda: {show_edit_form: gr.update(visible=False)}, outputs=[show_edit_form] ) # Notes handlers save_note_btn.click( lambda note: { note_display: note_display.value + f"\n• {note}" if note else note_display.value }, inputs=quick_note, outputs=[note_display] ) clear_note_btn.click( lambda: {quick_note: gr.update(value="")}, outputs=[quick_note] ) # Refresh button (hidden, used for updates) refresh_btn = gr.Button("Refresh", visible=False) refresh_btn.click(refresh_task_list, outputs=[task_list, task_count, weekly_stats_html, weekly_schedule]) # ============================================================================ # LAUNCH APPLICATION # ============================================================================ demo.launch( theme=gr.themes.Soft( primary_hue="indigo", secondary_hue="purple", neutral_hue="slate", font=gr.themes.GoogleFont("Inter"), text_size="lg", spacing_size="lg", radius_size="md" ), title="Schedule & Note Management App", description="A lightweight application for managing tasks, events, reminders, and fees. Based on PRD v1.0", css=""" .gradio-container { max-width: 1200px !important; } #weekly-stats, #fee-task-list { margin-bottom: 20px; } #search-input { border-radius: 8px; } """, footer_links=[ {"label": "Documentation", "url": "#"}, {"label": "Support", "url": "#"}, {"api": "api"} ] )