migrate remaining admin pages to inline feedback

Replace put_flash with inline feedback for form saves:
- Media library: metadata save shows "Saved" checkmark
- Product show: storefront controls save shows "Saved" checkmark
- Newsletter campaign form: draft save shows "Saved" checkmark

Page-level outcomes (uploads, deletes, async operations) remain as
flash/banner messages — these are the correct pattern for non-form
actions.

Completes Task 4 of notification overhaul.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jamey 2026-03-08 07:34:17 +00:00
parent 0834437340
commit db28cb8d9f
4 changed files with 23 additions and 14 deletions

View File

@ -76,7 +76,7 @@ Replace floating toast/flash messages with inline feedback and persistent top ba
| 1 | Build inline feedback component | 1.5h | done |
| 2 | Build persistent top banner component (replaces flash) | 1.5h | done |
| 3 | Migrate admin forms to inline feedback (theme, pages, settings, email, providers) | 3h | done |
| 4 | Migrate remaining admin pages (media, products, activity, newsletter, redirects, nav) | 2h | planned |
| 4 | Migrate remaining admin pages (media, products, activity, newsletter, redirects, nav) | 2h | done |
| 5 | Migrate shop pages (cart, contact, checkout, auth) | 2h | planned |
| 6 | Migrate setup wizard notifications | 1h | planned |
| 7 | Remove old flash/toast CSS and JS | 30m | planned |

View File

@ -17,6 +17,7 @@ defmodule BerrypodWeb.Admin.Media do
|> assign(:edit_form, nil)
|> assign(:upload_alt, "")
|> assign(:confirm_delete, false)
|> assign(:metadata_status, :idle)
|> allow_upload(:media_upload,
accept: ~w(.png .jpg .jpeg .webp .svg .gif),
max_entries: 1,
@ -114,7 +115,8 @@ defmodule BerrypodWeb.Admin.Media do
|> assign(:selected_image, Map.put(image, :data, nil))
|> assign(:selected_usages, usages)
|> assign(:edit_form, form)
|> assign(:confirm_delete, false)}
|> assign(:confirm_delete, false)
|> assign(:metadata_status, :idle)}
else
{:noreply, socket}
end
@ -141,10 +143,10 @@ defmodule BerrypodWeb.Admin.Media do
socket
|> stream_insert(:images, updated_no_blob)
|> assign(:selected_image, updated_no_blob)
|> put_flash(:info, "Metadata updated")}
|> assign(:metadata_status, :saved)}
{:error, _changeset} ->
{:noreply, put_flash(socket, :error, "Failed to update metadata")}
{:noreply, assign(socket, :metadata_status, :error)}
end
end
@ -398,9 +400,12 @@ defmodule BerrypodWeb.Admin.Media do
<.input field={@edit_form[:alt]} label="Alt text" placeholder="Describe this image..." />
<.input field={@edit_form[:caption]} label="Caption" placeholder="Optional caption..." />
<.input field={@edit_form[:tags]} label="Tags" placeholder="hero, homepage, banner..." />
<div class="admin-form-actions-sm">
<button type="submit" class="admin-btn admin-btn-primary admin-btn-sm">
Save metadata
</button>
<.inline_feedback status={@metadata_status} />
</div>
</.form>
<%= if @selected_usages != [] do %>

View File

@ -10,7 +10,8 @@ defmodule BerrypodWeb.Admin.Newsletter.CampaignForm do
|> assign(:page_title, "New campaign")
|> assign(:campaign, nil)
|> assign(:subscriber_count, Newsletter.confirmed_subscriber_count())
|> assign(:form, to_form(%{"subject" => "", "body" => ""}, as: :campaign))}
|> assign(:form, to_form(%{"subject" => "", "body" => ""}, as: :campaign))
|> assign(:save_status, :idle)}
end
@impl true
@ -42,7 +43,7 @@ defmodule BerrypodWeb.Admin.Newsletter.CampaignForm do
@impl true
def handle_event("validate", %{"campaign" => params}, socket) do
{:noreply, assign(socket, :form, to_form(params, as: :campaign))}
{:noreply, assign(socket, form: to_form(params, as: :campaign), save_status: :idle)}
end
def handle_event("save_draft", %{"campaign" => params}, socket) do
@ -51,10 +52,10 @@ defmodule BerrypodWeb.Admin.Newsletter.CampaignForm do
{:noreply,
socket
|> assign(:campaign, campaign)
|> put_flash(:info, "Campaign saved")}
|> assign(:save_status, :saved)}
{:error, _changeset} ->
{:noreply, put_flash(socket, :error, "Please fill in subject and body")}
{:noreply, assign(socket, :save_status, :error)}
end
end
@ -211,6 +212,7 @@ defmodule BerrypodWeb.Admin.Newsletter.CampaignForm do
<.button type="submit">
Save draft
</.button>
<.inline_feedback status={@save_status} />
<button
type="button"

View File

@ -27,6 +27,7 @@ defmodule BerrypodWeb.Admin.ProductShow do
|> assign(:page_title, product.title)
|> assign(:product, product)
|> assign(:form, form)
|> assign(:save_status, :idle)
{:ok, socket}
end
@ -40,7 +41,7 @@ defmodule BerrypodWeb.Admin.ProductShow do
|> Map.put(:action, :validate)
|> to_form(as: "product")
{:noreply, assign(socket, :form, form)}
{:noreply, assign(socket, form: form, save_status: :idle)}
end
@impl true
@ -63,12 +64,12 @@ defmodule BerrypodWeb.Admin.ProductShow do
socket
|> assign(:product, product)
|> assign(:form, form)
|> put_flash(:info, "Product updated")
|> assign(:save_status, :saved)
{:noreply, socket}
{:error, changeset} ->
{:noreply, assign(socket, :form, to_form(changeset, as: "product"))}
{:noreply, assign(socket, form: to_form(changeset, as: "product"), save_status: :error)}
end
end
@ -206,6 +207,7 @@ defmodule BerrypodWeb.Admin.ProductShow do
/>
</label>
<.button type="submit" variant="primary" class="admin-btn-sm">Save</.button>
<.inline_feedback status={@save_status} />
</.form>
</div>
</div>