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:
- Query Templates: Fetch active templates with recurrence patterns
- Query Instances: Fetch explicit task instances for the date range
- Generate Virtual Tasks: Create task objects for each template occurrence
- Merge and Deduplicate: Combine template-generated and instance tasks
- 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
- Task Selection: User selects incomplete task from Daily View
- Modal Presentation:
TaskCompletionModalopens with task context - Log Creation: Care log entry created with task details
- Instance Update: Task instance marked complete with log reference
- Inventory Updates: Consumables automatically deducted from inventory
- 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)
Modal System
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
- Individual Task Alerts: Specific notifications for time-sensitive tasks
- Daily Summary: Consolidated daily task list delivered each morning
- 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
- Batch Operations: Bulk task creation and modification
- Advanced Recurrence: Custom recurrence patterns beyond daily/weekly/monthly
- Task Dependencies: Sequential task workflows with completion prerequisites
- Team Collaboration: Shared task templates and assignment delegation
- Analytics Dashboard: Task completion metrics and care trend analysis
Performance Improvements
- Virtual Scrolling: Handle extremely large task lists efficiently
- Background Sync: Offline task completion with sync on reconnection
- Predictive Caching: Pre-fetch likely task data based on user patterns