2026-02-18 21:23:15 +00:00
|
|
|
defmodule BerrypodWeb.Admin.OrderShow do
|
|
|
|
|
use BerrypodWeb, :live_view
|
2026-02-07 21:59:14 +00:00
|
|
|
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
alias Berrypod.{ActivityLog, Orders}
|
2026-02-18 21:23:15 +00:00
|
|
|
alias Berrypod.Cart
|
2026-02-07 21:59:14 +00:00
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
|
def mount(%{"id" => id}, _session, socket) do
|
|
|
|
|
case Orders.get_order(id) do
|
|
|
|
|
nil ->
|
|
|
|
|
socket =
|
|
|
|
|
socket
|
|
|
|
|
|> put_flash(:error, "Order not found")
|
|
|
|
|
|> push_navigate(to: ~p"/admin/orders")
|
|
|
|
|
|
|
|
|
|
{:ok, socket}
|
|
|
|
|
|
|
|
|
|
order ->
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
if connected?(socket), do: ActivityLog.subscribe(order.id)
|
|
|
|
|
|
|
|
|
|
timeline = ActivityLog.list_for_order(order.id)
|
|
|
|
|
|
2026-02-07 21:59:14 +00:00
|
|
|
socket =
|
|
|
|
|
socket
|
|
|
|
|
|> assign(:page_title, order.order_number)
|
|
|
|
|
|> assign(:order, order)
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
|> assign(:timeline, timeline)
|
2026-02-07 21:59:14 +00:00
|
|
|
|
|
|
|
|
{:ok, socket}
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
@impl true
|
|
|
|
|
def handle_info({:new_activity, entry}, socket) do
|
|
|
|
|
{:noreply, assign(socket, :timeline, socket.assigns.timeline ++ [entry])}
|
|
|
|
|
end
|
|
|
|
|
|
2026-02-07 21:59:14 +00:00
|
|
|
@impl true
|
|
|
|
|
def render(assigns) do
|
|
|
|
|
~H"""
|
2026-02-12 08:35:22 +00:00
|
|
|
<.header>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<.link navigate={~p"/admin/orders"} class="admin-link-subtle" style="font-weight: 400;">
|
2026-02-12 08:35:22 +00:00
|
|
|
← Orders
|
|
|
|
|
</.link>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<div class="admin-row" style="--admin-row-gap: 0.75rem; margin-top: 0.25rem;">
|
|
|
|
|
<span style="font-size: 1.5rem; font-weight: 700;">{@order.order_number}</span>
|
2026-02-12 08:35:22 +00:00
|
|
|
<.status_badge status={@order.payment_status} />
|
|
|
|
|
</div>
|
|
|
|
|
</.header>
|
|
|
|
|
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<div class="admin-grid" style="--admin-grid-min: 20rem; --admin-grid-gap: 1.5rem; margin-top: 1.5rem;">
|
2026-02-12 08:35:22 +00:00
|
|
|
<%!-- order info --%>
|
2026-02-17 23:05:01 +00:00
|
|
|
<div class="admin-card">
|
|
|
|
|
<div class="admin-card-body">
|
|
|
|
|
<h3 class="admin-card-title">Order details</h3>
|
2026-02-12 08:35:22 +00:00
|
|
|
<.list>
|
|
|
|
|
<:item title="Date">{format_date(@order.inserted_at)}</:item>
|
|
|
|
|
<:item title="Customer">{@order.customer_email || "—"}</:item>
|
|
|
|
|
<:item title="Payment status">
|
|
|
|
|
<.status_badge status={@order.payment_status} />
|
|
|
|
|
</:item>
|
|
|
|
|
<:item :if={@order.stripe_payment_intent_id} title="Stripe payment">
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<code style="font-size: 0.75rem;">{@order.stripe_payment_intent_id}</code>
|
2026-02-12 08:35:22 +00:00
|
|
|
</:item>
|
|
|
|
|
<:item title="Currency">{String.upcase(@order.currency)}</:item>
|
|
|
|
|
</.list>
|
2026-02-07 21:59:14 +00:00
|
|
|
</div>
|
2026-02-12 08:35:22 +00:00
|
|
|
</div>
|
2026-02-07 21:59:14 +00:00
|
|
|
|
2026-02-12 08:35:22 +00:00
|
|
|
<%!-- shipping address --%>
|
2026-02-17 23:05:01 +00:00
|
|
|
<div class="admin-card">
|
|
|
|
|
<div class="admin-card-body">
|
|
|
|
|
<h3 class="admin-card-title">Shipping address</h3>
|
2026-02-12 08:35:22 +00:00
|
|
|
<%= if @order.shipping_address != %{} do %>
|
2026-02-07 21:59:14 +00:00
|
|
|
<.list>
|
2026-02-12 08:35:22 +00:00
|
|
|
<:item :if={@order.shipping_address["name"]} title="Name">
|
|
|
|
|
{@order.shipping_address["name"]}
|
|
|
|
|
</:item>
|
|
|
|
|
<:item :if={@order.shipping_address["line1"]} title="Address">
|
|
|
|
|
{@order.shipping_address["line1"]}
|
|
|
|
|
<span :if={@order.shipping_address["line2"]}>
|
|
|
|
|
<br />{@order.shipping_address["line2"]}
|
|
|
|
|
</span>
|
|
|
|
|
</:item>
|
|
|
|
|
<:item :if={@order.shipping_address["city"]} title="City">
|
|
|
|
|
{@order.shipping_address["city"]}
|
|
|
|
|
</:item>
|
|
|
|
|
<:item :if={@order.shipping_address["state"] not in [nil, ""]} title="State">
|
|
|
|
|
{@order.shipping_address["state"]}
|
2026-02-07 21:59:14 +00:00
|
|
|
</:item>
|
2026-02-12 08:35:22 +00:00
|
|
|
<:item :if={@order.shipping_address["postal_code"]} title="Postcode">
|
|
|
|
|
{@order.shipping_address["postal_code"]}
|
|
|
|
|
</:item>
|
|
|
|
|
<:item :if={@order.shipping_address["country"]} title="Country">
|
|
|
|
|
{@order.shipping_address["country"]}
|
2026-02-07 21:59:14 +00:00
|
|
|
</:item>
|
|
|
|
|
</.list>
|
2026-02-12 08:35:22 +00:00
|
|
|
<% else %>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<p class="admin-section-desc" style="margin-top: 0;">No shipping address provided</p>
|
2026-02-12 08:35:22 +00:00
|
|
|
<% end %>
|
2026-02-07 21:59:14 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-02-12 08:35:22 +00:00
|
|
|
</div>
|
2026-02-07 21:59:14 +00:00
|
|
|
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
<%!-- timeline --%>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<div class="admin-card" style="margin-top: 1.5rem;">
|
2026-02-17 23:05:01 +00:00
|
|
|
<div class="admin-card-body">
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<div class="admin-row" style="justify-content: space-between;">
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
<h3 class="admin-card-title">Timeline</h3>
|
2026-02-12 08:35:22 +00:00
|
|
|
<.fulfilment_badge status={@order.fulfilment_status} />
|
|
|
|
|
</div>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<div class="admin-row" style="margin-top: 0.5rem; margin-bottom: 1rem;">
|
2026-02-12 08:35:22 +00:00
|
|
|
<button
|
|
|
|
|
:if={can_submit?(@order)}
|
|
|
|
|
phx-click="submit_to_provider"
|
2026-02-17 23:05:01 +00:00
|
|
|
class="admin-btn admin-btn-primary admin-btn-sm"
|
2026-02-12 08:35:22 +00:00
|
|
|
>
|
|
|
|
|
<.icon name="hero-paper-airplane-mini" class="size-4" />
|
|
|
|
|
{if @order.fulfilment_status == "failed",
|
|
|
|
|
do: "Retry submission",
|
|
|
|
|
else: "Submit to provider"}
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
:if={can_refresh?(@order)}
|
|
|
|
|
phx-click="refresh_status"
|
2026-02-17 23:05:01 +00:00
|
|
|
class="admin-btn admin-btn-ghost admin-btn-sm"
|
2026-02-12 08:35:22 +00:00
|
|
|
>
|
|
|
|
|
<.icon name="hero-arrow-path-mini" class="size-4" /> Refresh status
|
|
|
|
|
</button>
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
</div>
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
<div
|
|
|
|
|
:if={@order.tracking_number not in [nil, ""]}
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
class="admin-row"
|
|
|
|
|
style="margin-bottom: 1rem; font-size: 0.875rem;"
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<span class="admin-text-secondary"><.icon name="hero-truck-mini" class="size-4" /></span>
|
|
|
|
|
<span style="font-weight: 500;">{@order.tracking_number}</span>
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
<a
|
|
|
|
|
:if={@order.tracking_url not in [nil, ""]}
|
|
|
|
|
href={@order.tracking_url}
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener"
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
class="admin-link"
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
>
|
|
|
|
|
Track shipment →
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
<.order_timeline entries={@timeline} />
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
</div>
|
2026-02-12 08:35:22 +00:00
|
|
|
</div>
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
|
2026-02-12 08:35:22 +00:00
|
|
|
<%!-- line items --%>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<div class="admin-card" style="margin-top: 1.5rem;">
|
2026-02-17 23:05:01 +00:00
|
|
|
<div class="admin-card-body">
|
|
|
|
|
<h3 class="admin-card-title">Items</h3>
|
|
|
|
|
<table class="admin-table admin-table-zebra">
|
2026-02-12 08:35:22 +00:00
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>Product</th>
|
|
|
|
|
<th>Variant</th>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<th style="text-align: end;">Qty</th>
|
|
|
|
|
<th style="text-align: end;">Unit price</th>
|
|
|
|
|
<th style="text-align: end;">Total</th>
|
2026-02-12 08:35:22 +00:00
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr :for={item <- @order.items}>
|
|
|
|
|
<td>{item.product_name}</td>
|
|
|
|
|
<td>{item.variant_title}</td>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<td style="text-align: end;">{item.quantity}</td>
|
|
|
|
|
<td style="text-align: end;">{Cart.format_price(item.unit_price)}</td>
|
|
|
|
|
<td style="text-align: end;">{Cart.format_price(item.unit_price * item.quantity)}</td>
|
2026-02-12 08:35:22 +00:00
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
<tfoot>
|
|
|
|
|
<tr>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<td colspan="4" style="text-align: end; font-weight: 500;">Subtotal</td>
|
|
|
|
|
<td style="text-align: end; font-weight: 500;">{Cart.format_price(@order.subtotal)}</td>
|
2026-02-12 08:35:22 +00:00
|
|
|
</tr>
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<tr style="font-size: 1.125rem;">
|
|
|
|
|
<td colspan="4" style="text-align: end; font-weight: 700;">Total</td>
|
|
|
|
|
<td style="text-align: end; font-weight: 700;">{Cart.format_price(@order.total)}</td>
|
2026-02-12 08:35:22 +00:00
|
|
|
</tr>
|
|
|
|
|
</tfoot>
|
|
|
|
|
</table>
|
2026-02-07 21:59:14 +00:00
|
|
|
</div>
|
2026-02-12 08:35:22 +00:00
|
|
|
</div>
|
2026-02-07 21:59:14 +00:00
|
|
|
"""
|
|
|
|
|
end
|
|
|
|
|
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
@impl true
|
|
|
|
|
def handle_event("submit_to_provider", _params, socket) do
|
|
|
|
|
order = socket.assigns.order
|
|
|
|
|
|
|
|
|
|
case Orders.submit_to_provider(order) do
|
|
|
|
|
{:ok, updated} ->
|
|
|
|
|
socket =
|
|
|
|
|
socket
|
|
|
|
|
|> assign(:order, updated)
|
|
|
|
|
|> put_flash(:info, "Order submitted to provider")
|
|
|
|
|
|
|
|
|
|
{:noreply, socket}
|
|
|
|
|
|
|
|
|
|
{:error, _reason} ->
|
|
|
|
|
order = Orders.get_order(order.id)
|
|
|
|
|
|
|
|
|
|
socket =
|
|
|
|
|
socket
|
|
|
|
|
|> assign(:order, order)
|
|
|
|
|
|> put_flash(:error, order.fulfilment_error || "Submission failed")
|
|
|
|
|
|
|
|
|
|
{:noreply, socket}
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def handle_event("refresh_status", _params, socket) do
|
|
|
|
|
order = socket.assigns.order
|
|
|
|
|
|
|
|
|
|
case Orders.refresh_fulfilment_status(order) do
|
|
|
|
|
{:ok, updated} ->
|
|
|
|
|
socket =
|
|
|
|
|
socket
|
|
|
|
|
|> assign(:order, updated)
|
|
|
|
|
|> put_flash(:info, "Status refreshed")
|
|
|
|
|
|
|
|
|
|
{:noreply, socket}
|
|
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
|
{:noreply, put_flash(socket, :error, "Failed to refresh: #{inspect(reason)}")}
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
# ── Components ──
|
|
|
|
|
|
|
|
|
|
defp order_timeline(assigns) do
|
|
|
|
|
~H"""
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<div :if={@entries == []} class="admin-section-desc" style="padding-block: 1rem; margin-top: 0;">
|
add activity log with order timeline and global feed
Single activity_log table powering two views: chronological timeline
on each order detail page (replacing the old fulfilment card) and a
global feed at /admin/activity with tabs, category filters, search,
and pagination. Real-time via PubSub — new entries appear instantly,
nav badge updates across all admin pages.
Instrumented across all event points: Stripe webhooks, order notifier,
submission worker, fulfilment status worker, product sync worker, and
Oban exhausted-job telemetry. Contextual action buttons (retry
submission, retry sync, dismiss) with Oban unique constraints to
prevent double-enqueue. 90-day pruning via cron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:09:08 +00:00
|
|
|
No activity recorded yet.
|
|
|
|
|
</div>
|
|
|
|
|
<ol :if={@entries != []} class="admin-timeline" id="order-timeline">
|
|
|
|
|
<li :for={entry <- @entries} class="admin-timeline-item">
|
|
|
|
|
<div class={["admin-timeline-dot", timeline_dot_class(entry.level)]}></div>
|
|
|
|
|
<div class="admin-timeline-content">
|
|
|
|
|
<p class="admin-timeline-message">{entry.message}</p>
|
|
|
|
|
<time class="admin-timeline-time" datetime={DateTime.to_iso8601(entry.occurred_at)}>
|
|
|
|
|
{format_timeline_time(entry.occurred_at)}
|
|
|
|
|
</time>
|
|
|
|
|
</div>
|
|
|
|
|
</li>
|
|
|
|
|
</ol>
|
|
|
|
|
"""
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
defp timeline_dot_class("error"), do: "admin-timeline-dot-error"
|
|
|
|
|
defp timeline_dot_class("warning"), do: "admin-timeline-dot-warning"
|
|
|
|
|
defp timeline_dot_class(_), do: "admin-timeline-dot-info"
|
|
|
|
|
|
|
|
|
|
defp format_timeline_time(datetime) do
|
|
|
|
|
today = Date.utc_today()
|
|
|
|
|
event_date = DateTime.to_date(datetime)
|
|
|
|
|
diff_days = Date.diff(today, event_date)
|
|
|
|
|
|
|
|
|
|
cond do
|
|
|
|
|
diff_days == 0 -> Calendar.strftime(datetime, "%H:%M")
|
|
|
|
|
diff_days < 7 -> Calendar.strftime(datetime, "%d %b %H:%M")
|
|
|
|
|
true -> Calendar.strftime(datetime, "%d %b %Y")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
defp can_submit?(order) do
|
|
|
|
|
order.payment_status == "paid" and order.fulfilment_status in ["unfulfilled", "failed"]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
defp can_refresh?(order) do
|
|
|
|
|
not is_nil(order.provider_order_id) and
|
|
|
|
|
order.fulfilment_status in ["submitted", "processing", "shipped"]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
defp fulfilment_badge(assigns) do
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
{color, icon} =
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
case assigns.status do
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
"submitted" -> {"admin-status-pill-blue", "hero-paper-airplane-mini"}
|
|
|
|
|
"processing" -> {"admin-status-pill-amber", "hero-cog-6-tooth-mini"}
|
|
|
|
|
"shipped" -> {"admin-status-pill-purple", "hero-truck-mini"}
|
|
|
|
|
"delivered" -> {"admin-status-pill-green", "hero-check-circle-mini"}
|
|
|
|
|
"failed" -> {"admin-status-pill-red", "hero-x-circle-mini"}
|
|
|
|
|
"cancelled" -> {"admin-status-pill-zinc", "hero-no-symbol-mini"}
|
|
|
|
|
_ -> {"admin-status-pill-zinc", "hero-minus-circle-mini"}
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
end
|
|
|
|
|
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
assigns = assign(assigns, color: color, icon: icon)
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
|
|
|
|
|
~H"""
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<span class={["admin-status-pill", @color]}>
|
feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent
guards, Stripe address mapping, and error handling. Track fulfilment
status through submitted → processing → shipped → delivered via
webhook-driven updates (primary) and Oban Cron polling fallback.
- 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps)
- OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment
- FulfilmentStatusWorker polls every 30 mins for missed webhook events
- Printify order webhook handlers (sent-to-production, shipment, delivered)
- Admin UI: fulfilment column in table, fulfilment card with tracking info,
submit/retry and refresh buttons on order detail
- Mox provider mocking for test isolation (Provider.for_type configurable)
- 33 new tests (555 total), verified against real Printify API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 09:51:51 +00:00
|
|
|
<.icon name={@icon} class="size-3" /> {@status}
|
|
|
|
|
</span>
|
|
|
|
|
"""
|
|
|
|
|
end
|
|
|
|
|
|
2026-02-07 21:59:14 +00:00
|
|
|
defp status_badge(assigns) do
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
{color, icon} =
|
2026-02-07 21:59:14 +00:00
|
|
|
case assigns.status do
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
"paid" -> {"admin-status-pill-green", "hero-check-circle-mini"}
|
|
|
|
|
"pending" -> {"admin-status-pill-amber", "hero-clock-mini"}
|
|
|
|
|
"failed" -> {"admin-status-pill-red", "hero-x-circle-mini"}
|
|
|
|
|
"refunded" -> {"admin-status-pill-zinc", "hero-arrow-uturn-left-mini"}
|
|
|
|
|
_ -> {"admin-status-pill-zinc", "hero-question-mark-circle-mini"}
|
2026-02-07 21:59:14 +00:00
|
|
|
end
|
|
|
|
|
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
assigns = assign(assigns, color: color, icon: icon)
|
2026-02-07 21:59:14 +00:00
|
|
|
|
|
|
|
|
~H"""
|
refactor admin CSS: replace utility classes with semantic styles
Replace Tailwind utility soup across admin templates with semantic
CSS classes. Add layout primitives (stack, row, cluster, grid),
extract JS transition helpers into transitions.css, and refactor
core_components, layouts, settings, newsletter, order_show, providers,
and theme editor templates.
Utility occurrences reduced from 290+ to 127 across admin files.
All 1679 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:15:25 +00:00
|
|
|
<span class={["admin-status-pill", @color]}>
|
2026-02-07 21:59:14 +00:00
|
|
|
<.icon name={@icon} class="size-3" /> {@status}
|
|
|
|
|
</span>
|
|
|
|
|
"""
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
defp format_date(datetime) do
|
|
|
|
|
Calendar.strftime(datetime, "%d %b %Y %H:%M")
|
|
|
|
|
end
|
|
|
|
|
end
|