Class: Ace::Support::Items::Molecules::StatusCategorizer

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/support/items/molecules/status_categorizer.rb

Overview

Categorizes items into “up next” and “recently done” buckets for status overview displays. Generic — works with any item responding to :status, :file_path, :special_folder, :id.

Class Method Summary collapse

Class Method Details

.categorize(items, up_next_limit:, recently_done_limit:, pending_statuses: ["pending"], done_statuses: ["done"], up_next_sorter: nil) ⇒ Hash

Returns { up_next: […], recently_done: [{ item:, completed_at: }] }.

Parameters:

  • items (Array)

    All loaded items

  • up_next_limit (Integer)

    Max up-next items (0 = disable section)

  • recently_done_limit (Integer)

    Max recently-done items (0 = disable section)

  • pending_statuses (Array<String>) (defaults to: ["pending"])

    Statuses considered “up next”

  • done_statuses (Array<String>) (defaults to: ["done"])

    Statuses considered “recently done”

  • up_next_sorter (Proc, nil) (defaults to: nil)

    Custom sorter for up-next items. Receives array of items, returns sorted array. Default: sort by id.

Returns:

  • (Hash)

    { up_next: […], recently_done: [{ item:, completed_at: }] }



19
20
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
# File 'lib/ace/support/items/molecules/status_categorizer.rb', line 19

def self.categorize(items, up_next_limit:, recently_done_limit:,
  pending_statuses: ["pending"], done_statuses: ["done"],
  up_next_sorter: nil)
  up_next = if up_next_limit > 0
    candidates = items
      .select { |i| pending_statuses.include?(i.status) && i.special_folder.nil? }
    sorted = if up_next_sorter
      up_next_sorter.call(candidates)
    else
      candidates.sort_by(&:id)
    end
    sorted.first(up_next_limit)
  else
    []
  end

  recently_done = if recently_done_limit > 0
    items
      .select { |i| done_statuses.include?(i.status) }
      .map { |i| {item: i, completed_at: safe_mtime(i.file_path)} }
      .sort_by { |entry| -(entry[:completed_at]&.to_f || 0) }
      .first(recently_done_limit)
  else
    []
  end

  {up_next: up_next, recently_done: recently_done}
end