Skip to content

Instantly share code, notes, and snippets.

@ryanbrunner
Created January 22, 2024 01:09
Show Gist options
  • Save ryanbrunner/f463b1e287c3f89f3142578892015011 to your computer and use it in GitHub Desktop.
Save ryanbrunner/f463b1e287c3f89f3142578892015011 to your computer and use it in GitHub Desktop.
<div class="mt-8 flow-root" data-controller="table-component">
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
<div class="relative">
<table class="min-w-full table-fixed border-collapse">
<thead class="border-solid border-0 border-b border-gray-200">
<tr>
<th scope="col" class="min-w-[12rem] py-3.5 pr-3 text-left text-sm font-semibold text-gray-900">
<%= columns.first.heading %>
</th>
<% columns[1..].each do |column| %>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 hidden md:table-cell">
<%= column.heading %>
</th>
<% end %>
</tr>
</thead>
<tbody class="bg-white">
<% collection.each do |item| %>
<tr class="border-solid border-0 border-b border-gray-200 last:border-b-0">
<td class="whitespace-nowrap py-4 pr-3 text-sm font-medium text-gray-900">
<%= columns.first.cell(item) %>
</td>
<% columns[1..].each do |column| %>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500 hidden md:table-cell">
<%= column.cell(item) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
# frozen_string_literal: true
module Ui
class TableComponent < ViewComponent::Base
renders_many :columns, "TableColumnComponent"
attr_reader :collection
def initialize(collection:)
raise ArgumentError, "collection must be enumerable" unless collection.respond_to?(:each)
@collection = collection
end
def column_names
columns.map(&:name)
end
class TableColumnComponent < ViewComponent::Base
include DatetimeHelper
attr_reader :name, :mobile_hidden
def initialize(name, display: nil, heading: nil, mobile_hidden: false)
@name = name
@display = display
@heading = heading
@mobile_hidden = mobile_hidden
end
def heading
@heading || name.to_s.humanize
end
def cell(record)
if @display
@display.call(record).to_s.html_safe
else
val = record.send(name)
case val
when ActiveSupport::TimeWithZone
time_in_words_or_absolute(val)
else
val.to_s
end
end
end
end
end
end
<%= render Ui::TableComponent.new(collection: @emails) do |table| %>
<% table.with_column(:sent_to) %>
<% if @display_type == "User" %>
<% table.with_column(:feed_item_title, heading: "Item") %>
<% end %>
<% table.with_column(:state, display: -> (email) do
style = case email.state
when "opened"
"positive"
when "bounced"
"negative"
else
"neutral"
end
render PillComponent.new(text: email.state.titleize, style: style)
end) %>
<% table.with_column(:delivered_at, heading: "Sent") %>
<% table.with_column(:opened_at, heading: "Opened") %>
<% end %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment