Commit Graph

38 Commits

Author SHA1 Message Date
jamey
7c07805df8 add nav editors to Site tab with live preview
All checks were successful
deploy / deploy (push) Successful in 3m27s
- Add header and footer nav editors to Site tab with drag-to-reorder,
  add/remove items, and destination picker (pages, collections, external)
- Live preview updates as you edit nav items
- Remove legacy /admin/navigation page and controller (was saving to
  Settings table, now uses nav_items table)
- Update error_html.ex and pages/editor.ex to load nav from nav_items table
- Update link_scanner to read from nav_items table, edit path now /?edit=site
- Add Site.default_header_nav/0 and default_footer_nav/0 for previews/errors
- Remove fallback logic from theme_hook.ex (database is now source of truth)
- Seed default nav items and social links during setup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 22:19:48 +00:00
jamey
2282af91db complete onboarding UX v2
Some checks failed
deploy / deploy (push) Has been cancelled
Tasks C, H, I from the plan:

- Forgiving API key validation: add Printify UUID format and Printful
  length validation, validate on blur for fast feedback, helpful error
  messages with specific guidance

- External links UX: verified all external links use <.external_link>
  component with target="_blank", rel="noopener noreferrer", icon, and
  screen reader text

- Input styling WCAG compliance: increase input border contrast from
  ~3.3:1 to ~4.5-5:1 across all theme moods (neutral, warm, cool, dark)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-10 07:56:54 +00:00
jamey
6f0b7f4f63 redirect /admin/theme to on-site editor at /?edit=theme
All checks were successful
deploy / deploy (push) Successful in 1m41s
- Phase 5 was already implemented (URL mode activation via ?edit param)
- Phase 6: Add RedirectController to redirect /admin/theme → /?edit=theme
- Update admin sidebar and dashboard links to point directly to /?edit=theme
- Delete old Admin.Theme.Index LiveView and template (no longer needed)
- Update tests for new redirect behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 20:30:33 +00:00
jamey
32cc425458 separate account settings from shop settings
All checks were successful
deploy / deploy (push) Successful in 3m28s
- Create dedicated /admin/account page for user account management
- Move email, password, and 2FA settings from /admin/settings
- Add Account link to top of admin sidebar navigation
- Add TOTP-based two-factor authentication with NimbleTOTP
- Add TOTP verification LiveView for login flow
- Add AccountController for TOTP session management
- Remove Advanced section from settings (duplicated in dev tools)
- Remove user email from sidebar footer (replaced by Account link)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 18:42:29 +00:00
jamey
3e29a89fff add link picker and validation to navigation editor
All checks were successful
deploy / deploy (push) Successful in 1m26s
- replace freeform inputs with grouped dropdown (pages, custom pages,
  collections, external URL)
- add inline URL validation for external links
- add inline feedback component instead of flash messages
- add dismiss-on-interaction pattern (feedback clears on changes)
- add no-JS fallback via NavigationController
- add DirtyGuard hook to warn before navigating away with unsaved changes
- add no-JS fallbacks for settings forms (from address, signing secret)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 02:10:06 +00:00
jamey
42542ac177 migrate admin forms to inline feedback
All checks were successful
deploy / deploy (push) Successful in 1m26s
Replace put_flash calls with inline feedback for form saves:
- Email settings: "Now send a test email" after saving
- Settings: from address and signing secret saves
- Page editor: save button shows "Saved" checkmark

Inline feedback appears next to save buttons and auto-clears after
3 seconds. Banners (put_flash) remain for page-level outcomes like
deletions, state changes, and async operations.

Task 3 of notification overhaul. Theme editor skipped as it auto-saves.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-07 21:01:54 +00:00
jamey
c6636cab65 improve email settings progressive enhancement and admin layout
Some checks failed
deploy / deploy (push) Has been cancelled
- semantic HTML: step numbers inside h2, strong provider names, details
  for adapter configs, strong error messages, fieldset drawer toggle hidden
- inline field errors via flash for no-JS controller fallback
- single form POST button for test email (works with and without JS)
- admin sidebar: remove brand/view-shop, move user email to footer nav
- replace inline style with .admin-setup-step-spaced class
- clean up unused CSS (.admin-brand, .admin-sidebar-header, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:29:05 +00:00
jamey
5dee2ae0be fix email settings: hidden attr for no-CSS, block-level card labels
All checks were successful
deploy / deploy (push) Successful in 1m29s
Non-selected adapter configs now get HTML hidden attribute so only the
active config shows without CSS. Provider card labels use div instead
of span for natural block stacking in text-only rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:40:35 +00:00
jamey
db130a7155 rework email settings for true progressive enhancement
All checks were successful
deploy / deploy (push) Successful in 1m19s
Render all adapter field sections in the form with CSS :has(:checked)
controlling visibility. Selecting a provider instantly shows its config
fields — no JS, no page reload, no server round-trip needed.

- Render all 6 adapter configs with data-adapter attribute
- CSS :has(:checked) show/hide rules per adapter in admin stylesheet
- Namespace field names per adapter (email[brevo][api_key] etc)
- Drop 4 transactional-only providers (Resend, Postmark, Mailgun, MailPace)
- Remove noscript "Switch provider" button and controller redirect workaround
- Remove configured_adapter hidden input tracking
- Hide JS-only test email button for no-JS users via noscript style
- LiveView progressively enhances with async save and test email

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:10:37 +00:00
jamey
dd20ea824f fix email settings: missing providers, a11y, no-JS support
show all 10 providers in three groups (popular, transactional,
advanced) with category headings. fix phx-change clobbering text
fields, async test email sending state, integer parse crash on
bad port. add keyboard focus on card radios, fieldset legend,
WCAG-compliant badge contrast, responsive grid. extract shared
save_config into Mailer, add no-JS controller fallback with
configured_adapter hidden field for adapter change detection.
remove CardRadioScroll JS hook (no longer needed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:26:59 +00:00
jamey
7547d0d4b8 rework email settings UX with guided flow and friendly errors
grouped providers by category, added per-provider key validation
with cross-provider detection, friendly delivery error messages,
retryable vs config error distinction, from-address in general
settings, and "Save settings" button to match admin conventions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:12:10 +00:00
jamey
76cff0494e add forgiving API key validation with inline errors
Add KeyValidation module for format-checking API keys before
attempting connections. Auto-strips whitespace, detects common
mistakes (e.g. pasting a Stripe publishable key), and returns
helpful error messages.

Inline field errors across all three entry points:
- Setup wizard: provider + Stripe keys
- Admin provider form: simplified to single Connect button
- Email settings: per-field errors instead of flash toasts

Also: plain text inputs for all API keys (not password fields),
accessible error states (aria-invalid, role=alert, thick border,
bold text), inner_block slot declaration on error component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:17:56 +00:00
jamey
64f083d271 improve setup UX: password field, setup hook, checklist banners, theme tweaks
All checks were successful
deploy / deploy (push) Successful in 1m31s
- add password field and required shop name to setup wizard
- extract SetupHook for DRY redirect to /setup when no admin exists
- add ?from=checklist param to checklist hrefs with contextual banner on
  email settings and theme pages for easy return to dashboard
- remove email warning banner from admin layout (checklist covers it)
- make email a required checklist item (no longer optional)
- add DevReset module for wiping dev data without restart
- rename "Theme Studio" to "Theme", drop subtitle
- lower theme editor side-by-side breakpoint from 64em to 48em
- clean up login/registration pages (remove dead registration_open code)
- fix settings.put_secret to invalidate cache after write

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:41:08 +00:00
jamey
0853b6f528 share provider connection logic between setup wizard and providers form
Extract Products.connect_provider/2 that tests the connection, fetches
shop_id, creates the record, and enqueues sync. Both the setup wizard
and the providers form now use this shared function instead of
duplicating the flow. Also makes the products empty state context-aware
(distinguishes "no provider" from "provider connected but no products").

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:19:17 +00:00
jamey
5b41f3fedf extract site_name and site_description from theme settings into standalone settings
site_name and site_description are shop identity, not theme concerns.
They now live in the Settings table as first-class settings with their
own assigns (@site_name, @site_description) piped through hooks and
plugs. The setup wizard writes site_name on account creation, and the
theme editor reads/writes via Settings.put_setting. Removed the
"configure your shop" checklist item since currency/country aren't
built yet. Also adds shop name field to setup wizard step 1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 14:52:31 +00:00
jamey
bf06ee051a hide system events by default on activity page
All checks were successful
deploy / deploy (push) Successful in 1h1m58s
Adds a toggle to show/hide internal system events (syncs, job failures,
abandoned cart creation) on the activity feed. Hidden by default so shop
owners only see actionable items. Toggle is ephemeral — resets on page load.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 08:32:06 +00:00
jamey
580a7203c9 add activity log with order timeline and global feed
All checks were successful
deploy / deploy (push) Successful in 4m22s
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
jamey
ad2e6d1e6d add newsletter and email campaigns
Subscribers with double opt-in confirmation, campaign composer with
draft/scheduled/sent lifecycle, admin dashboard with overview stats,
CSV export, and shop signup form wired into page builder blocks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:25:28 +00:00
jamey
0a7982dfe8 add admin UX polish: nav grouping, inline settings, real preview data
All checks were successful
deploy / deploy (push) Successful in 1m33s
- sidebar nav grouped under Shop/Content/Settings section headers with
  subtle uppercase labels (#105)
- custom page settings now show inline in a collapsible panel within the
  editor instead of navigating away to a separate page (#107)
- admin editor preview loads real products and categories from the DB,
  falling back to PreviewData only on fresh installs (#108)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 20:17:03 +00:00
jamey
93ff66debc add legal page editor integration and media library polish
Some checks failed
deploy / deploy (push) Has been cancelled
Legal pages (privacy, delivery, terms) now auto-populate content from
shop settings on mount, show auto-generated vs customised badges, and
have a regenerate button. Theme editor gains alt text fields for logo,
header, and icon images. Image picker in page builder now has an upload
button and alt text warning badges. Clearing unused image references
shows an orphan info flash.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:55:02 +00:00
jamey
79b5161e02 add undo/redo to page editors with keyboard shortcuts
All checks were successful
deploy / deploy (push) Successful in 1m29s
History stacks (@history/@future) on both admin editor and live sidebar,
capped at 50 entries. All mutations routed through apply_mutation for
consistent history tracking. EditorKeyboard JS hook combines DirtyGuard
with Ctrl+Z/Ctrl+Shift+Z. Settings panel fade-in animation. 10 new tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 12:16:15 +00:00
jamey
3a243151af add data-driven navigation with admin editor
All checks were successful
deploy / deploy (push) Successful in 1m34s
Replace hardcoded header, footer and mobile nav with settings-driven
loops. Nav items stored as JSON via Settings, loaded in ThemeHook with
sensible defaults. New admin navigation editor at /admin/navigation
for add/remove/reorder/save/reset. Mobile bottom nav also driven from
header nav items with icon mapping by slug.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 11:18:37 +00:00
jamey
045be2ed7e add admin CRUD for custom CMS pages
All checks were successful
deploy / deploy (push) Successful in 1m21s
New settings form for creating and editing custom page metadata
(title, slug, meta description, published, nav settings). Pages
index shows custom pages section with draft badges and delete.
Editor shows settings button for custom pages, hides reset to
defaults. 20 new tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 09:43:03 +00:00
jamey
847b5f3e5e add admin media library with image management and block picker integration
- Schema: alt, caption, tags fields on images table with metadata changeset
- Context: list_images with filters, find_usages, used_image_ids, delete_with_cleanup
- Admin UI: /admin/media with grid view, upload, filters, detail panel, metadata editing
- Block editor: :image field type for image_text and content_body blocks
- Page renderer: image_id resolution with legacy URL fallback
- Mobile: bottom sheet detail panel with slide-up animation
- CSS: uses correct --t-* admin theme tokens, admin-badge colour variants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:20:51 +00:00
jamey
b340c24aa1 add live preview pane to page editor
All checks were successful
deploy / deploy (push) Successful in 4m55s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 08:06:17 +00:00
jamey
6fbd654d57 add SettingsField struct and repeater field type for block settings
All checks were successful
deploy / deploy (push) Successful in 1m23s
Introduces typed settings schema with SettingsField struct, replaces
the read-only JSON textarea with a full repeater UI for info_card items.
Supports add, remove, reorder and inline editing of repeater items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 00:54:13 +00:00
jamey
3f97742c0b add inline block settings editing to page editor
All checks were successful
deploy / deploy (push) Successful in 3m40s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 21:47:24 +00:00
jamey
660fda928f add admin page editor with block reordering and management
Stage 6 of the page builder: admin UI at /admin/pages for managing
page layouts. Page list shows all 14 pages grouped by category.
Editor supports reorder (up/down), add, remove, duplicate, save,
and reset to defaults. DirtyGuard JS hook warns on unsaved changes.
ARIA live regions announce block operations for screen readers.

Also: regenerate admin icons (81 rules via mix task with @layer
wrapping), add gen_smtp dep for SMTP email adapter, add :key to
page renderer block loop for correct LiveView diffing.

1309 tests, 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 21:15:01 +00:00
jamey
0b0adba0fe add no-JS progressive enhancement for all shop flows
All checks were successful
deploy / deploy (push) Successful in 1m23s
Every key shop flow now works via plain HTML forms when JS is
unavailable. LiveView progressively enhances when JS connects.

- PDP: form wraps variant/qty/add-to-cart with action="/cart/add"
- Cart page: qty +/- and remove use form POST fallbacks
- Cart/search header icons are now links with phx-click enhancement
- Collection sort form has GET action + noscript submit button
- New /search page with form-based search for no-JS users
- CartController gains add/remove/update_item POST actions
- CartHook gains update_quantity_form and remove_item_form handlers
- Fix flaky analytics tests caused by event table pollution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:56:19 +00:00
jamey
7ceee9c814 add dashboard filtering to analytics
All checks were successful
deploy / deploy (push) Successful in 1m19s
Click any row in pages, sources, countries, or devices tables to
filter the entire dashboard by that dimension. Active filters show
as dismissible chips. Filters thread through all queries including
previous-period deltas. 1050 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:46:34 +00:00
jamey
6eda1de1bc add period comparison deltas to analytics stat cards
All checks were successful
deploy / deploy (push) Successful in 1m21s
Each stat card now shows the percentage change vs the equivalent
previous period (e.g. 30d compares last 30 days vs 30 days before).
Handles zero-baseline with "new" label and caps extreme deltas at
>999%. Seed data extended to 2 years for meaningful 12m comparisons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:01:25 +00:00
jamey
2bd2e613c7 add privacy-first analytics with progressive event collection
All checks were successful
deploy / deploy (push) Successful in 3m20s
Three-layer pipeline: Plug for all HTTP requests (no JS needed), LiveView
hook for SPA navigations, JS hook for screen width. ETS-backed buffer
batches writes to SQLite every 10s. Daily-rotating salt for visitor hashing.
Includes admin dashboard with date ranges, visitor trends, top pages,
sources, devices, and e-commerce conversion funnel. Oban cron for 12-month
data retention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 12:50:55 +00:00
jamey
069fbc7df2 add tests for email verification flag lifecycle
All checks were successful
deploy / deploy (push) Successful in 34s
Tests that sending a test email sets the verified flag, saving config
clears it, and disconnecting clears it. Also adds unit tests for
email_verified?/mark/clear in the Mailer module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:43:33 +00:00
jamey
194fec8240 namespace email settings keys per adapter
All checks were successful
deploy / deploy (push) Successful in 57s
Settings keys like api_key were shared across providers, so switching
from e.g. Postmark to SendGrid showed the old API key. Now each
adapter gets its own namespaced key (email_postmark_api_key, etc.)
so credentials persist independently and switching back pre-fills
previously saved values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:57:23 +00:00
jamey
366a1e6a48 add admin email settings page with provider selection
All checks were successful
deploy / deploy (push) Successful in 56s
Card radio component for picking email providers (SMTP, SendGrid, Mailjet, etc.)
with instant client-side switching via JS hook. Adapter configs are pre-rendered
and toggled without a server round-trip. Secrets are preserved when re-saving
with blank password fields. Includes from address field, test email sending,
and disconnect flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:29:34 +00:00
jamey
c2caeed64d add setup onboarding page, dashboard launch checklist, provider registry
- new /setup page with three-section onboarding (account, provider, payments)
- dashboard launch checklist with progress bar, go-live, dismiss
- provider registry on Provider module (single source of truth for metadata)
- payments registry for Stripe
- setup context made provider-agnostic (provider_connected, theme_customised, etc.)
- admin provider pages now fully registry-driven (no hardcoded provider names)
- auth flow: fresh installs redirect to /setup, signed_in_path respects setup state
- removed old /admin/setup wizard
- 840 tests, 0 failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:34:06 +00:00
jamey
559798206f extract setup wizard to dedicated /admin/setup page
Move the setup stepper out of the dashboard into its own LiveView.
Dashboard now redirects to setup when site isn't live, and shows
stats-only view once live. Also cleans up button component variant
handling, fixes alert CSS, and removes stale demo.html.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 23:55:42 +00:00
jamey
9528700862 rename project from SimpleshopTheme to Berrypod
All modules, configs, paths, and references updated.
836 tests pass, zero warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:23:15 +00:00