Class: Reclaim::Client
- Inherits:
-
Object
- Object
- Reclaim::Client
- Defined in:
- lib/reclaim/client.rb
Overview
HTTP client for Reclaim API interactions
Constant Summary collapse
- BASE_URL =
'https://api.app.reclaim.ai/api'
Instance Method Summary collapse
-
#complete_task(task_id) ⇒ Object
Mark a task as complete.
-
#create_task(title:, due_date: nil, priority: :p3, duration: 1.0, min_chunk_size: nil, max_chunk_size: nil, min_work_duration: nil, max_work_duration: nil, snooze_until: nil, start: nil, time_scheme: nil, always_private: nil, event_category: nil, event_color: nil, notes: nil, allow_splitting: false, split_chunk_size: nil) ⇒ Object
Create a new task.
-
#delete_task(task_id) ⇒ Object
Delete a task.
-
#format_time_schemes ⇒ Object
Get formatted list of time schemes for display.
-
#get_task(task_id) ⇒ Object
Get a specific task by ID.
-
#initialize(token = nil) ⇒ Client
constructor
A new instance of Client.
-
#list_tasks(filter: nil) ⇒ Object
List all tasks with optional filtering.
-
#list_time_schemes ⇒ Object
List all available time schemes.
-
#update_task(task_id, title: nil, notes: nil, priority: nil, due_date: :unset, duration: nil, min_chunk_size: nil, max_chunk_size: nil, min_work_duration: nil, max_work_duration: nil, snooze_until: :unset, start: :unset, time_scheme: nil, always_private: nil, event_category: nil, event_color: nil) ⇒ Object
Update an existing task.
Constructor Details
#initialize(token = nil) ⇒ Client
Returns a new instance of Client.
13 14 15 16 17 18 |
# File 'lib/reclaim/client.rb', line 13 def initialize(token = nil) @token = token || ENV['RECLAIM_API_KEY'] raise AuthenticationError, 'RECLAIM_API_KEY environment variable not set' unless @token @time_schemes_cache = nil end |
Instance Method Details
#complete_task(task_id) ⇒ Object
Mark a task as complete
169 170 171 172 173 174 175 176 177 |
# File 'lib/reclaim/client.rb', line 169 def complete_task(task_id) # Use PATCH to update status to ARCHIVED to match Reclaim app behavior response = make_request(:patch, "/tasks/#{task_id}", { status: 'ARCHIVED' }) Task.new(response) rescue ApiError => e raise NotFoundError, "Task #{task_id} not found" if e.status_code == 404 raise end |
#create_task(title:, due_date: nil, priority: :p3, duration: 1.0, min_chunk_size: nil, max_chunk_size: nil, min_work_duration: nil, max_work_duration: nil, snooze_until: nil, start: nil, time_scheme: nil, always_private: nil, event_category: nil, event_color: nil, notes: nil, allow_splitting: false, split_chunk_size: nil) ⇒ Object
Create a new task
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/reclaim/client.rb', line 21 def create_task(title:, due_date: nil, priority: :p3, duration: 1.0, min_chunk_size: nil, max_chunk_size: nil, min_work_duration: nil, max_work_duration: nil, snooze_until: nil, start: nil, time_scheme: nil, always_private: nil, event_category: nil, event_color: nil, notes: nil, allow_splitting: false, split_chunk_size: nil) # Resolve time scheme if provided time_scheme_id = time_scheme ? resolve_time_scheme_id(time_scheme) : nil if time_scheme && !time_scheme_id raise InvalidRecordError, "Time scheme '#{time_scheme}' not found. Use list_time_schemes to see available options." end # Set chunk sizes based on splitting preference duration_chunks = (duration * 4).to_i # Convert hours to 15-minute chunks if allow_splitting # Allow splitting: use provided chunk sizes or defaults # Use split_chunk_size if provided, otherwise use min_chunk_size or default if split_chunk_size min_chunk = (split_chunk_size * 4).to_i elsif min_chunk_size min_chunk = (min_chunk_size * 4).to_i else min_chunk = 1 # Default 15 minutes end max_chunk = max_chunk_size ? (max_chunk_size * 4).to_i : 12 # Default 3 hours else # Prevent splitting: set both min and max to full duration min_chunk = duration_chunks max_chunk = duration_chunks end task_data = { title: title, priority: Task::PRIORITIES[priority] || 'P3', timeChunksRequired: duration_chunks, eventCategory: event_category || 'WORK', eventSubType: 'FOCUS', minChunkSize: min_chunk, maxChunkSize: max_chunk } # Add optional fields (using actual API field names) task_data[:due] = Utils.format_datetime_for_api(due_date) if due_date task_data[:notes] = notes if notes # Note: minChunkSize and maxChunkSize are now set above based on allow_splitting task_data[:minWorkDuration] = (min_work_duration * 4).to_i if min_work_duration task_data[:maxWorkDuration] = (max_work_duration * 4).to_i if max_work_duration task_data[:snoozeUntil] = Utils.format_datetime_for_api(snooze_until) if snooze_until task_data[:start] = Utils.format_datetime_for_api(start) if start task_data[:timeSchemeId] = time_scheme_id if time_scheme_id task_data[:alwaysPrivate] = always_private if always_private task_data[:eventCategory] = event_category if event_category task_data[:eventColor] = event_color if event_color response = make_request(:post, '/tasks', task_data) Task.new(response) end |
#delete_task(task_id) ⇒ Object
Delete a task
180 181 182 183 184 185 186 187 |
# File 'lib/reclaim/client.rb', line 180 def delete_task(task_id) make_request(:delete, "/tasks/#{task_id}") true rescue ApiError => e raise NotFoundError, "Task #{task_id} not found" if e.status_code == 404 raise end |
#format_time_schemes ⇒ Object
Get formatted list of time schemes for display
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/reclaim/client.rb', line 195 def format_time_schemes schemes = list_time_schemes return "No time schemes found." if schemes.empty? output = "\nAvailable Time Schemes:\n" output += "-" * 50 + "\n" schemes.each do |scheme| title = scheme['title'] || 'Untitled' scheme_id = scheme['id'] || 'N/A' policy_type = scheme['policyType'] || 'N/A' output += "• #{title}\n" output += " ID: #{scheme_id}\n" output += " Type: #{policy_type}\n\n" end output += "Usage: time_scheme: \"Work Hours\" or time_scheme: \"work\"\n" output end |
#get_task(task_id) ⇒ Object
Get a specific task by ID
99 100 101 102 103 104 105 106 |
# File 'lib/reclaim/client.rb', line 99 def get_task(task_id) response = make_request(:get, "/tasks/#{task_id}") Task.new(response) rescue ApiError => e raise NotFoundError, "Task #{task_id} not found" if e.status_code == 404 raise end |
#list_tasks(filter: nil) ⇒ Object
List all tasks with optional filtering
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/reclaim/client.rb', line 81 def list_tasks(filter: nil) response = make_request(:get, '/tasks') tasks = response.map { |task_data| Task.new(task_data) } # Apply client-side filtering since API doesn't support server-side filtering case filter when :active tasks.select(&:active?) when :completed tasks.select(&:completed?) when :overdue tasks.select(&:overdue?) else tasks end end |
#list_time_schemes ⇒ Object
List all available time schemes
190 191 192 |
# File 'lib/reclaim/client.rb', line 190 def list_time_schemes get_time_schemes end |
#update_task(task_id, title: nil, notes: nil, priority: nil, due_date: :unset, duration: nil, min_chunk_size: nil, max_chunk_size: nil, min_work_duration: nil, max_work_duration: nil, snooze_until: :unset, start: :unset, time_scheme: nil, always_private: nil, event_category: nil, event_color: nil) ⇒ Object
Update an existing task
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/reclaim/client.rb', line 109 def update_task(task_id, title: nil, notes: nil, priority: nil, due_date: :unset, duration: nil, min_chunk_size: nil, max_chunk_size: nil, min_work_duration: nil, max_work_duration: nil, snooze_until: :unset, start: :unset, time_scheme: nil, always_private: nil, event_category: nil, event_color: nil) # Build update data with only provided fields # Use :unset as sentinel to distinguish "not provided" from "explicitly nil (clear)" update_data = {} update_data[:title] = title if title update_data[:notes] = notes if notes update_data[:priority] = Task::PRIORITIES[priority] if priority # Handle dates: :unset means not provided, nil means clear, value means set if due_date != :unset update_data[:due] = due_date.nil? ? nil : Utils.format_datetime_for_api(due_date) end update_data[:timeChunksRequired] = (duration * 4).to_i if duration update_data[:minChunkSize] = (min_chunk_size * 4).to_i if min_chunk_size update_data[:maxChunkSize] = (max_chunk_size * 4).to_i if max_chunk_size update_data[:minWorkDuration] = (min_work_duration * 4).to_i if min_work_duration update_data[:maxWorkDuration] = (max_work_duration * 4).to_i if max_work_duration # Handle snooze_until (deferred date) if snooze_until != :unset update_data[:snoozeUntil] = snooze_until.nil? ? nil : Utils.format_datetime_for_api(snooze_until) end # Handle start date if start != :unset update_data[:start] = start.nil? ? nil : Utils.format_datetime_for_api(start) end update_data[:alwaysPrivate] = always_private if always_private update_data[:eventCategory] = event_category if event_category update_data[:eventColor] = event_color if event_color # Resolve time scheme if provided if time_scheme time_scheme_id = resolve_time_scheme_id(time_scheme) if time_scheme_id update_data[:timeSchemeId] = time_scheme_id else raise InvalidRecordError, "Time scheme '#{time_scheme}' not found" end end raise InvalidRecordError, 'No update fields provided' if update_data.empty? response = make_request(:patch, "/tasks/#{task_id}", update_data) Task.new(response) rescue ApiError => e raise NotFoundError, "Task #{task_id} not found" if e.status_code == 404 raise end |