Current section

Files

Jump to
phoenix_kit_billing lib phoenix_kit modules billing web transactions.html.heex
Raw

lib/phoenix_kit/modules/billing/web/transactions.html.heex

<div class="container mx-auto px-4 py-6">
<%!-- Header --%>
<.admin_page_header back={PhoenixKit.Utils.Routes.path("/admin/billing")}>
<h1 class="text-xl sm:text-2xl lg:text-3xl font-bold text-base-content">Transactions</h1>
<p class="text-sm text-base-content/60 mt-0.5">{@total_count} total transactions</p>
<:actions>
<button phx-click="refresh" class="btn btn-ghost btn-sm">
<.icon name="hero-arrow-path" class="w-4 h-4" /> Refresh
</button>
</:actions>
</.admin_page_header>
<%!-- Filters --%>
<div class="card bg-base-100 shadow mb-6">
<div class="card-body py-4">
<form phx-change="filter" phx-submit="filter" class="flex flex-wrap gap-4 items-end">
<div class="form-control flex-1 min-w-[200px]">
<label class="label">
<span class="label-text">Search</span>
</label>
<input
type="text"
name="search"
value={@search}
placeholder="Transaction #, Invoice #..."
class="input input-bordered input-sm"
phx-debounce="300"
/>
</div>
<div class="form-control">
<label class="label">
<span class="label-text">Type</span>
</label>
<select name="type" class="select select-bordered select-sm">
<option value="all" selected={@type_filter == "all"}>All Types</option>
<option value="payment" selected={@type_filter == "payment"}>Payments</option>
<option value="refund" selected={@type_filter == "refund"}>Refunds</option>
</select>
</div>
<div class="form-control">
<label class="label">
<span class="label-text">Payment Method</span>
</label>
<select name="payment_method" class="select select-bordered select-sm">
<option value="all" selected={@payment_method_filter == "all"}>All Methods</option>
<option value="bank" selected={@payment_method_filter == "bank"}>
Bank Transfer
</option>
</select>
</div>
<button type="button" phx-click="clear_filters" class="btn btn-ghost btn-sm">
Clear Filters
</button>
</form>
</div>
</div>
<%!-- Transactions Table --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body p-0">
<%= if @loading do %>
<div class="flex justify-center items-center py-12">
<span class="loading loading-spinner loading-lg"></span>
</div>
<% else %>
<%= if Enum.empty?(@transactions) do %>
<div class="text-center py-12">
<.icon
name="hero-banknotes"
class="w-16 h-16 mx-auto mb-4 text-base-content/30"
/>
<h3 class="text-xl font-semibold mb-2">No transactions found</h3>
<p class="text-base-content/60 mb-4">
<%= if @search != "" or @type_filter != "all" or @payment_method_filter != "all" do %>
Try adjusting your filters or search terms
<% else %>
Transactions will appear here when payments or refunds are recorded
<% end %>
</p>
</div>
<% else %>
<div class="overflow-x-auto">
<table class="table">
<thead>
<tr>
<th>Transaction #</th>
<th>Invoice</th>
<th>Type</th>
<th>Amount</th>
<th>Method</th>
<th>Description</th>
<th>Date</th>
<th></th>
</tr>
</thead>
<tbody>
<%= for transaction <- @transactions do %>
<tr
class="hover cursor-pointer"
phx-click="view_invoice"
phx-value-uuid={transaction.invoice_uuid}
>
<td class="font-mono text-sm">{transaction.transaction_number}</td>
<td>
<%= if transaction.invoice do %>
<.link
navigate={
PhoenixKit.Utils.Routes.path(
"/admin/billing/invoices/#{transaction.invoice_uuid}"
)
}
class="link link-hover font-mono text-sm"
>
{transaction.invoice.invoice_number}
</.link>
<% else %>
<span class="text-base-content/50">-</span>
<% end %>
</td>
<td>
<.transaction_type_badge type={transaction_type(transaction)} />
</td>
<td>
<span class={[
"font-mono font-medium",
if(Decimal.positive?(transaction.amount),
do: "text-success",
else: "text-error"
)
]}>
<%= if Decimal.positive?(transaction.amount) do %>
+<.currency_compact
amount={transaction.amount}
currency={transaction.currency}
/>
<% else %>
<.currency_compact
amount={transaction.amount}
currency={transaction.currency}
/>
<% end %>
</span>
</td>
<td>
<span class="badge badge-outline badge-sm h-auto">
{String.upcase(transaction.payment_method || "bank")}
</span>
</td>
<td class="max-w-[200px] truncate text-sm text-base-content/70">
{transaction.description || "-"}
</td>
<td class="text-sm text-base-content/60">
<.time_ago datetime={transaction.inserted_at} />
</td>
<td>
<.link
navigate={
PhoenixKit.Utils.Routes.path(
"/admin/billing/invoices/#{transaction.invoice_uuid}"
)
}
class="btn btn-xs btn-outline btn-info tooltip tooltip-bottom"
data-tip={gettext("View Invoice")}
>
<.icon name="hero-eye" class="w-4 h-4 hidden sm:inline" />
<span class="sm:hidden whitespace-nowrap">
{gettext("View Invoice")}
</span>
</.link>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<%!-- Pagination --%>
<%= if @total_pages > 1 do %>
<div class="flex justify-center py-4">
<.pagination
current_page={@page}
total_pages={@total_pages}
base_path={PhoenixKit.Utils.Routes.path("/admin/billing/transactions")}
params={
%{
"search" => @search,
"type" => @type_filter,
"payment_method" => @payment_method_filter
}
}
/>
</div>
<% end %>
<% end %>
<% end %>
</div>
</div>
</div>