Task Management Architecture

System Overview

The task management system in CrittrHavens implements a template-instance pattern that separates recurring task definitions from individual scheduled occurrences. This architecture allows for flexible scheduling while maintaining data consistency and performance.

Core Components

Template-Instance Pattern: TaskTemplate entities define recurring schedules, while TaskInstance entities represent individual scheduled occurrences that can be independently modified without affecting the template.

Dynamic Generation: The system generates task instances on-demand rather than pre-creating them, optimizing database usage and allowing for real-time schedule adjustments.

Automatic Logging: Task completion creates audit trails through the logging system, providing comprehensive care history tracking.

Type Definitions

TaskTemplate Interface

interface TaskTemplate {
  id: string;
  user_id: string;
  name: string;
  description?: string;
  log_type: string;                    // Links to care log categories
  milestone_type?: string;             // Optional milestone classification
  related_items_data?: any;            // Linked crittrs/habitats/plants
  consumables_data?: any;              // Inventory tracking data
  start_date: string;                  // Template activation date
  end_date?: string;                   // Optional template expiration
  time_of_day?: string;                // Default scheduling time
  recurrence_pattern?: RecurrencePattern;
  is_active: boolean;                  // Template state control
  created_at: string;
  updated_at: string;
}

RecurrencePattern Types

interface RecurrencePattern {
  type: 'daily' | 'weekly' | 'monthly';
  interval: number;                    // Every N days/weeks/months
  days?: string[];                     // Weekly: ['monday', 'wednesday']
  day_of_month?: number;               // Monthly: specific day (1-31)
}

GeneratedTask Union

The GeneratedTask interface represents the unified view used by UI components, combining template and instance data:

interface GeneratedTask {
  id: string;
  template?: TaskTemplate;             // Source template if applicable
  instance?: TaskInstance;             // Individual instance if modified
  date: string;                        // Scheduled date
  time?: string;                       // Scheduled time
  name: string;                        // Display name
  description?: string;                // Task description
  log_type: string;                    // Log type for completion logging
  milestone_type?: string;             // Optional milestone classification
  related_items_data?: any;            // Linked crittrs/habitats/plants
  consumables_data?: any;              // Inventory tracking data
  is_completed: boolean;               // Completion status
  is_generated: boolean;               // True for template-generated tasks
  log_id?: string;                     // Link to completion log
}

Task Generation Algorithm

Weekly Task Resolution

The useTasks hook implements a sophisticated task generation algorithm:

  1. Query Templates: Fetch active templates with recurrence patterns
  2. Query Instances: Fetch explicit task instances for the date range
  3. Generate Virtual Tasks: Create task objects for each template occurrence
  4. Merge and Deduplicate: Combine template-generated and instance tasks
  5. Apply Overrides: Instance modifications override template defaults

Recurrence Logic

// Daily recurrence: every N days from start_date
const isDaily = (template, date) => {
  const daysSinceStart = Math.floor(
    (date.getTime() - template.start_date.getTime()) / (1000 * 60 * 60 * 24)
  );
  return daysSinceStart >= 0 && daysSinceStart % template.recurrence_pattern.interval === 0;
};

// Weekly recurrence: specific days every N weeks
const isWeekly = (template, date) => {
  const daysSinceStart = Math.floor(
    (date.getTime() - template.start_date.getTime()) / (1000 * 60 * 60 * 24)
  );
  const dayOfWeek = format(date, 'EEEE').toLowerCase();
  const weeksSinceStart = Math.floor(daysSinceStart / 7);
  return daysSinceStart >= 0 &&
         template.recurrence_pattern.days.includes(dayOfWeek) &&
         weeksSinceStart % template.recurrence_pattern.interval === 0;
};

Database Schema

Task Templates Table

CREATE TABLE task_templates (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES auth.users(id),
  name TEXT NOT NULL,
  description TEXT,
  log_type TEXT NOT NULL,
  milestone_type TEXT,
  related_items_data JSONB,
  consumables_data JSONB,
  start_date DATE NOT NULL,
  end_date DATE,
  time_of_day TIME,
  recurrence_pattern JSONB,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT now(),
  updated_at TIMESTAMP DEFAULT now()
);

Task Instances Table

CREATE TABLE task_instances (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  template_id UUID REFERENCES task_templates(id),
  user_id UUID REFERENCES auth.users(id),
  scheduled_date DATE NOT NULL,
  scheduled_time TIME,
  name TEXT,                           -- Override template name
  description TEXT,                    -- Override template description
  related_items_data JSONB,            -- Override template items
  consumables_data JSONB,              -- Override template consumables
  is_completed BOOLEAN DEFAULT false,
  completed_at TIMESTAMP,
  log_id UUID REFERENCES care_logs(id),
  is_deleted BOOLEAN DEFAULT false,
  is_modified BOOLEAN DEFAULT false,   -- Tracks template overrides
  created_at TIMESTAMP DEFAULT now(),
  updated_at TIMESTAMP DEFAULT now()
);

Task Completion Workflow

Completion Process

  1. Task Selection: User selects incomplete task from Daily View
  2. Modal Presentation: TaskCompletionModal opens with task context
  3. Log Creation: Care log entry created with task details
  4. Instance Update: Task instance marked complete with log reference
  5. Inventory Updates: Consumables automatically deducted from inventory
  6. Audit Trail: Completion timestamps and user actions logged

Code Flow

const completeTask = useMutation({
  mutationFn: async ({ task, logData }) => {
    // Create log entry
    const { data: log } = await supabase
      .from('logs')
      .insert({
        user_id: user.id,
        subject: logData.subject || task.name,
        content: logData.content,
        log_type: task.log_type,
        milestone_type: task.milestone_type,
        reference_id: logData.reference_id,
        related_items_data: logData.related_items
          ? { related_items: logData.related_items }
          : task.related_items_data,
        consumables_data: logData.consumables
          ? { consumables: logData.consumables }
          : task.consumables_data,
        log_date: logData.log_date || new Date().toISOString(),
        images: logData.images
      })
      .select()
      .single();

    // Create or update task instance
    if (task.instance) {
      const { error: updateError } = await supabase
        .from('task_instances')
        .update({ is_completed: true, completed_at: new Date().toISOString(), log_id: log.id })
        .eq('id', task.instance.id)
      if (updateError) throw updateError
    } else if (task.template) {
      const { error: insertError } = await supabase.from('task_instances').insert({
        user_id: user.id,
        template_id: task.template.id,
        scheduled_date: task.date,
        scheduled_time: task.time,
        is_completed: true,
        completed_at: new Date().toISOString(),
        log_id: log.id,
      })
      if (insertError) throw insertError
    }
  }
});

UI Component Architecture

Component Hierarchy

Tasks.tsx (Page)
├── IOSHeaderWithTabs (Navigation)
├── TasksView (Daily/Schedule View)
│   ├── TasksCalendar (Calendar Display)
│   ├── TaskCompletionModal (Complete Tasks)
│   ├── EditTaskInstanceModal (Modify Instances)
│   ├── EditTaskTemplateModal (Template Editor)
│   └── CreateTaskModal (Quick Tasks & Templates)
└── ScheduleView (Template Management)
    └── CareListContainer (Template List)

The task system uses a comprehensive modal architecture:

  • TaskCompletionModal: Handles task completion with log creation
  • CreateTaskModal: Creates both one-time tasks and recurring templates
  • EditTaskInstanceModal: Modifies individual task instances
  • EditTaskTemplateModal: Updates entire template series

Push Notification System

Notification Architecture

The system integrates with Supabase Edge Functions for push notifications:

interface SchedulePushNotificationParams {
  taskId: string;
  taskName: string;
  scheduledDate: string;
  scheduledTime?: string;
  relatedItems?: any[];
}

interface SendPushNotificationParams {
  userId?: string;
  userIds?: string[];
  title: string;
  body: string;
  data?: Record<string, any>;
  taskId?: string;
  scheduledDate?: string;
}

Notification Types

  1. Individual Task Alerts: Specific notifications for time-sensitive tasks
  2. Daily Summary: Consolidated daily task list delivered each morning
  3. Overdue Reminders: Alerts for incomplete tasks past their scheduled time

Implementation

const scheduleTaskNotification = async (params: SchedulePushNotificationParams) => {
  // Check if user prefers daily summary over individual notifications
  const dailySummaryEnabled = await checkDailySummaryEnabled();
  
  if (dailySummaryEnabled) {
    console.log('User has daily summary enabled, skipping individual task notification');
    return;
  }

  // Send notification using the send-push-notification function
  return supabase.functions.invoke('send-push-notification', {
    body: {
      userId: user.id,
      title: 'Task Reminder',
      body: `It's time for: ${params.taskName}`,
      data: { taskId: params.taskId, type: 'task_reminder' }
    }
  });
};

Performance Optimizations

Query Optimization

  • Date Range Queries: Limit template resolution to visible week ranges
  • Index Usage: Database indexes on user_id, scheduled_date, and is_active
  • Lazy Loading: Modal components load on-demand rather than pre-mounting

Caching Strategy

  • React Query: Aggressive caching of template and instance data
  • Optimistic Updates: UI updates immediately with rollback on failure
  • Background Sync: Automatic refetch on focus/connection restore

Memory Management

  • Component Unmounting: Proper cleanup of event listeners and subscriptions
  • State Normalization: Minimal duplicate data in component state
  • Pagination: Large task lists paginated to prevent memory bloat

Testing Strategy

Unit Testing Coverage

describe('Task Generation', () => {
  test('generates daily tasks correctly', () => {
    // Test daily recurrence pattern algorithm
  });

  test('handles weekly recurrence with specific days', () => {
    // Test weekly pattern with day constraints
  });

  test('respects template start/end dates', () => {
    // Test date boundary conditions
  });
});

describe('Task Completion', () => {
  test('creates log entry on completion', () => {
    // Test log creation workflow
  });

  test('updates inventory when consumables used', () => {
    // Test consumable deduction
  });
});

Integration Testing

  • API Endpoints: Test all Supabase CRUD operations
  • Modal Workflows: Test complete user interaction flows
  • Notification System: Test push notification scheduling and delivery

Security Considerations

Row Level Security

All task tables implement RLS policies:

-- Task templates policies
CREATE POLICY "Users can view their own task templates" 
ON task_templates FOR SELECT 
USING (auth.uid() = user_id);

CREATE POLICY "Users can create their own task templates" 
ON task_templates FOR INSERT 
WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update their own task templates" 
ON task_templates FOR UPDATE 
USING (auth.uid() = user_id);

CREATE POLICY "Users can delete their own task templates" 
ON task_templates FOR DELETE 
USING (auth.uid() = user_id);

-- Task instances policies
CREATE POLICY "Users can view their own task instances" 
ON task_instances FOR SELECT 
USING (auth.uid() = user_id);

CREATE POLICY "Users can create their own task instances" 
ON task_instances FOR INSERT 
WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update their own task instances" 
ON task_instances FOR UPDATE 
USING (auth.uid() = user_id);

CREATE POLICY "Users can delete their own task instances" 
ON task_instances FOR DELETE 
USING (auth.uid() = user_id);

Data Validation

  • Input Sanitization: All user inputs validated on client and server
  • Type Safety: Strict TypeScript interfaces prevent data corruption
  • Permission Checks: User authorization verified for all operations

API Security

  • Authentication Required: All endpoints require valid Supabase session
  • Rate Limiting: Edge Functions implement rate limiting for abuse prevention
  • Data Encryption: All data encrypted in transit and at rest

Future Enhancements

Planned Features

  1. Batch Operations: Bulk task creation and modification
  2. Advanced Recurrence: Custom recurrence patterns beyond daily/weekly/monthly
  3. Task Dependencies: Sequential task workflows with completion prerequisites
  4. Team Collaboration: Shared task templates and assignment delegation
  5. Analytics Dashboard: Task completion metrics and care trend analysis

Performance Improvements

  1. Virtual Scrolling: Handle extremely large task lists efficiently
  2. Background Sync: Offline task completion with sync on reconnection
  3. Predictive Caching: Pre-fetch likely task data based on user patterns