Commit Graph

39 Commits

Author SHA1 Message Date
jamey
04ce28ca29 fix page settings section and blocks not showing in editor
All checks were successful
deploy / deploy (push) Successful in 1m16s
Two bugs fixed:

1. Page Settings section wasn't appearing for system pages because
   Defaults.for_slug didn't return all required fields (type,
   meta_description, published, etc). Also changed page_renderer
   to use bracket notation for safer field access.

2. Blocks weren't loading when navigating directly to ?edit=page
   because the PageEditorHook's handle_params ran before Shop.Page
   assigned @page. Added pending page mode mechanism: hook sets a
   flag when edit mode is requested but @page is nil, then Shop.Page
   calls maybe_enter_pending_page_mode after @page is assigned.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-29 20:30:36 +01:00
jamey
9a506357eb complete editor panel reorganisation polish
All checks were successful
deploy / deploy (push) Successful in 6m49s
- fix Site tab not loading theme state on direct URL navigation
- fix nav editor showing "Custom URL" for page links (detect by URL match)
- add Home option to nav page picker
- mark editor-reorganisation plan as complete
- add dynamic-url-customisation and draft-publish-workflow plans

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-29 18:50:07 +01:00
jamey
d3fe6f4b56 add provider sync enhancements for product lifecycle
- add discontinued status to products (soft-delete when removed from provider)
- add availability helpers to variants (available/out_of_stock/discontinued)
- add detailed sync audit logging (product created/updated/discontinued)
- add cost change detection with threshold alerts (5% warning, 20% critical)
- update cart to show unavailable items with appropriate messaging
- block checkout when cart contains unavailable items
- show discontinued badge on product pages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-29 18:49:55 +01:00
jamey
dd7146cb41 merge page settings into Page tab and remove Settings tab
All checks were successful
deploy / deploy (push) Successful in 3m37s
Custom page settings (title, slug, meta, published, navigation) now
appear as a collapsible section at the top of the Page tab. The
separate Settings tab has been fully removed.

- Add page_settings_section component to page_renderer.ex
- Remove dead :settings case from editor_panel_content
- Delete settings_editor.ex component entirely
- Remove SettingsEditor import from shop_components.ex
- Add .page-settings-* CSS styles
- Clean up old .settings-* CSS styles

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 23:54:04 +00:00
jamey
242fed0501 move branding settings from Theme tab to Site tab
Some checks failed
deploy / deploy (push) Failing after 10m13s
- Add branding_editor component to site_editor.ex with:
  - Shop name input
  - Show shop name / Show logo toggles
  - Logo upload (size slider, SVG recolor, color picker)
  - Header background toggle and upload (zoom, position sliders)
- Add site_ prefixed event handlers in page_editor_hook.ex:
  - site_update_branding, site_toggle_branding, site_update_color
  - site_remove_logo and site_remove_header (delegate to theme handlers)
- Remove branding sections from theme_editor.ex:
  - Deleted shop_name_input, branding_section, logo/header upload sections
- Theme tab now shows only: preset grid, accent colours, customise accordion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 23:40:48 +00:00
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
638bb4fb70 add Site context with social links editor and site-wide settings
Some checks failed
deploy / deploy (push) Has been cancelled
- Add Site context for managing site-wide content (social links, nav items,
  announcement bar, footer content)
- Add SocialLink schema with URL normalization and platform auto-detection
  supporting 40+ platforms via host and 25+ via URI scheme
- Add NavItem schema for header/footer navigation (editor UI coming next)
- Add SiteEditor component with collapsible sections for each content type
- Wire social links card block and footer to use database data
- Filter empty URLs from display in shop components
- Add DetailsPreserver hook to preserve collapsible section state
- Add comprehensive tests for Site context and SocialLink functions
- Remove unused helper functions from onboarding to fix compiler warnings
- Move sync_edit_url_param helper to group handle_editor_event clauses

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 10:09:33 +00:00
jamey
a6e5db73c0 prevent checkout with unavailable product variants
- Include is_available flag in hydrated cart items
- Show unavailable message on cart items and product page
- Block add-to-cart for unavailable variants
- Redirect back to cart with error if checkout has unavailable items

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-13 13:34:22 +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
378b3fdb6b add image uploads to on-site theme editor and fix scroll on navigation
All checks were successful
deploy / deploy (push) Successful in 1m27s
Phase 4 of unified editing: image upload handling in hook context.
- Configure uploads in Shop.Page mount for logo, header, icon
- Add upload UI components to theme_editor compact_editor
- Pass uploads through page_renderer to theme editor
- Add cancel_upload handler to PageEditorHook

Also fixes scroll position not resetting on patch navigation:
- Push scroll-top event when path changes in handle_params
- JS listener scrolls window to top instantly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 19:45:43 +00:00
jamey
6aaddeaf44 fix settings editor crash on product pages
All checks were successful
deploy / deploy (push) Successful in 1m33s
The provider_label function was accessing product.provider_type but
that field is on the provider_connection association, not the product
itself. Handle the case where the association may not be preloaded.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 16:25:00 +00:00
jamey
f7891188e0 add settings editor component for unified on-site editing
All checks were successful
deploy / deploy (push) Successful in 4m13s
Phase 3b of unified editing mode. The Settings tab now shows
context-specific forms: custom pages get editable title, slug,
meta, visibility and nav options; system pages get read-only info
with links to admin; product/collection pages show provider info.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 15:38:06 +00:00
jamey
bb5d220079 consolidate shop pages into unified LiveView for editor state persistence
All checks were successful
deploy / deploy (push) Successful in 1m27s
Replace individual shop LiveViews with a single Shop.Page that dispatches
to page modules based on live_action. This enables patch navigation between
pages, preserving socket state (including editor state) across transitions.

Changes:
- Add Shop.Page unified LiveView with handle_params dispatch
- Extract page logic into Shop.Pages.* modules (Home, Product, Collection, etc.)
- Update router to use Shop.Page with live_action for all shop routes
- Change navigate= to patch= in shop component links
- Add maybe_sync_editing_blocks to reload editor state when page changes
- Track editor_page_slug to detect cross-page navigation while editing
- Fix picture element height when hover image disabled
- Extract ThemeEditor components for shared use

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 14:47:50 +00:00
jamey
168b6ce76f implement unified on-site editor phases 1-2
All checks were successful
deploy / deploy (push) Successful in 1m10s
Add theme editing to the existing PageEditorHook, enabling on-site
theme customisation alongside page editing. The editor panel now has
three tabs (Page, Theme, Settings) and can be collapsed while
keeping editing state intact.

- Add theme editing state and event handlers to PageEditorHook
- Add 3-tab UI with tab switching logic
- Add transparent overlay for click-outside dismiss
- Add mobile drag-to-resize with height persistence
- Fix animation replay on drag release (has-dragged class)
- Preserve panel height across LiveView re-renders
- Default to Page tab on editable pages, Theme otherwise
- Show unsaved changes indicator on FAB when panel collapsed
- Fix handle_event grouping warning in admin theme

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-09 09:01:21 +00:00
jamey
476da8121a add header background contrast warning and improve branding UX
All checks were successful
deploy / deploy (push) Successful in 1m12s
- extract dominant colors from header images during optimization
- calculate WCAG contrast ratios against theme text color
- show warning in theme editor when text may be hard to read
- prevent hiding shop name when no logo is uploaded
- auto-enable shop name when logo is deleted
- fix image cache invalidation on delete
- add missing .hidden utility class

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 22:40:08 +00:00
jamey
0c2d4ac406 add rate limiting and HSTS for security hardening
Some checks failed
deploy / deploy (push) Failing after 8m33s
- Add Hammer library for rate limiting with ETS backend
- Rate limit login (5/min), magic link (3/min), newsletter (10/min), API (60/min)
- Add themed 429 error page using bare shop styling
- Enable HSTS in production with rewrite_on for Fly proxy
- Add security hardening plan to docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 08:58:43 +00:00
jamey
5e03dccb69 improve notification accessibility
- use role="status" for info messages, role="alert" for errors
- add aria-live attribute (polite for info, assertive for errors)
- move phx-click to close button for better keyboard navigation
- add close buttons to shop flash messages
- add aria-hidden to decorative icons

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 07:53:17 +00:00
jamey
bd07c9c7d9 separate editor FAB and panel for cleaner animation
All checks were successful
deploy / deploy (push) Successful in 1m32s
Split the editor sheet into two distinct elements:
- .editor-fab: floating action button, always a pill in the corner
- .editor-panel: sliding panel that animates in/out independently

This enables proper CSS keyframe animations (slide-up/down on mobile,
slide-in/out on desktop) with a closing class for exit transitions.
Simplified the JS hook to only handle close behaviour.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-07 19:01:32 +00:00
jamey
f4f036b84b replace admin rail with unified bottom sheet editor
All checks were successful
deploy / deploy (push) Successful in 1m30s
- add editor sheet component anchored bottom (mobile) / right (desktop)
- admin cog moves to header, always visible for admins
- remove Done button from editor header, keep only Save
- add editor_at_defaults tracking to disable Reset when at defaults
- sheet collapses on click outside or Escape, stays in edit mode
- dirty indicator + beforeunload warning for unsaved changes
- keyboard shortcuts: Ctrl+Z undo, Ctrl+Shift+Z redo
- WCAG compliant: aria-expanded, live region, focus management

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-07 09:30:07 +00:00
jamey
dd659e4c61 replace orphaned tailwind classes with project CSS
All checks were successful
deploy / deploy (push) Successful in 1m27s
auth pages (login, registration, confirmation, recover) now use
setup-page/setup-header/admin-btn-block. theme toggle indicator
gets proper CSS. cleaned up dead h-full, size-3.5, ml-2 classes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:12:21 +00:00
jamey
67a26eb6b4 add contextual prompts for skipped setup steps
All checks were successful
deploy / deploy (push) Successful in 1m26s
Disable checkout when Stripe isn't connected (cart drawer, cart page,
and early guard in checkout controller to prevent orphaned orders).
Show amber warning on order detail when email isn't configured.
Fix pre-existing missing vertical spacing between page blocks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:02:49 +00:00
jamey
e139a75b69 consolidate all external links through external_link component
All checks were successful
deploy / deploy (push) Successful in 1m32s
Add icon={false} option to external_link for links with their own
visual indicator. Migrate remaining manual target="_blank" links:
email settings adapter links, product show provider edit, card radio
links, social link cards/icons, page renderer tracking and video
fallback. Every external link in the codebase now goes through the
single component — one place to change rel, target, or sr-only text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 07:12:25 +00:00
jamey
156a23da16 add external link UX: icons, rel attributes, screen reader labels
New external_link component in core_components handles target="_blank",
rel="noopener noreferrer", external-link icon, and sr-only "(opens in
new tab)" text. Migrated admin providers form, settings (Stripe),
order tracking, onboarding setup links to use it. Fixed rel="noopener"
to "noopener noreferrer" on remaining links (email settings, product
show, core_components card radio). Added sr-only text to shop social
link cards and aria-label to page renderer tracking link.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:55:09 +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
3480b326a9 add pagination across all admin and shop views
All checks were successful
deploy / deploy (push) Successful in 1m38s
URL-based offset pagination with ?page=N for bookmarkable pages.
Admin views use push_patch, shop collection uses navigate links.
Responsive on mobile with horizontal-scroll tables and stacking
pagination controls. Includes dev seed script for testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:42:34 +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
8f989d892d add block previews, picker thumbnails and newsletter settings
All checks were successful
deploy / deploy (push) Successful in 1m30s
Block cards now show a one-line content summary below the name.
Block picker items include SVG wireframe thumbnails. Newsletter
block marked as decorative with configurable title/description
and form submission prevented on the shop side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 20:34:52 +00:00
jamey
ca01f43d70 add no-JS contact form and noscript banner
All checks were successful
deploy / deploy (push) Successful in 1m21s
Wire up the contact form with action/method/name attrs so it works
without JavaScript. Add ContactNotifier, ContactController, and a
noscript info banner in the shop root layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:57:51 +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
a039c8d53c add live page editor sidebar with collapsible UI
All checks were successful
deploy / deploy (push) Successful in 6m49s
Admins can now edit pages directly on the live shop by clicking the
pencil icon in the header. A sidebar slides in with block management
controls (add, remove, reorder, edit settings, save, reset, done).

Key features:
- PageEditorHook on_mount with handle_params/event/info hooks
- BlockEditor pure functions extracted from admin editor
- Shared BlockEditorComponents with event_prefix namespacing
- Collapsible sidebar: X closes it, header pencil reopens it
- Backdrop overlay dismisses sidebar on tap
- Conditional admin.css loading for logged-in users
- content_body block now portable (textarea setting + rich text fallback)

13 integration tests, 26 unit tests, 1370 total passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 16:22:35 +00:00
jamey
23e95a3de6 make PDP variant selection work without JS
All checks were successful
deploy / deploy (push) Successful in 1m3s
Variant options (colour, size) are now URL params handled via
handle_params instead of phx-click events. Swatches and size buttons
render as patch links in shop mode, so changing variants works as
plain navigation without JS. Quantity is now a number input that
submits with the form. Unavailable variants render as disabled spans.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 01:08:36 +00:00
jamey
d0ea9d59f5 add no-JS fallback for cart country selector
All checks were successful
deploy / deploy (push) Successful in 59s
The delivery country form now has action="/cart/country" with a
noscript submit button. Without JS, changing the country and clicking
Update POSTs to a new CartController.update_country action that saves
the country to session and redirects back to /cart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 23:14:48 +00:00
jamey
6289c678f7 add no-JS fallback for contact page order tracking form
Some checks failed
deploy / deploy (push) Has been cancelled
Both order tracking forms now have action="/contact/lookup" so they
POST to a new OrderLookupController.lookup action when JS is off.
The controller mirrors the LiveView handler: checks for paid orders,
sends the verification email, and redirects with a flash message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 23:10:15 +00:00
jamey
c0427d6956 fix add-to-cart button not submitting in shop mode
All checks were successful
deploy / deploy (push) Successful in 1m5s
The button type condition checked @mode == :live but ThemeHook sets
mode to :shop, so the button rendered as type="button" (doing nothing).
Changed to @mode == :preview to match the existing phx-click pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:58:41 +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
12d87998ee make entire product card image area clickable
All checks were successful
deploy / deploy (push) Successful in 1m18s
The stretched-link::after overlay (z-index: 0) was blocked by
product-card-image-wrap (z-index: 1), so only the title text was
actually clickable. Wrapping the image area in a <.link> component
directly fixes this — taps/clicks bubble up to the link naturally,
and touch-scroll on the image carousel still works on mobile.

Also corrects the mode check: ThemeHook sets mode: :shop on shop pages,
not :live, so the condition is now mode != :preview (consistent with
how the title link already worked).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 15:22:43 +00:00
jamey
781ebc8cd8 fix privacy policy niggles and add last-updated date to legal pages
All checks were successful
deploy / deploy (push) Successful in 1m19s
- Capitalise lead sentence regardless of shop_name value
- Add stripe.com/privacy URL when mentioning Stripe in payment section
- Remove mention of logout from session cookie description
- Make third-party sharing text provider-agnostic (no longer names Printify etc.)
- Add :updated_at block to privacy, delivery, and terms pages showing when
  content last changed — auto-tracked via content hash, so the date advances
  automatically whenever relevant settings change

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 14:33:01 +00:00
jamey
01ff8decd5 add order status lookup for customers
All checks were successful
deploy / deploy (push) Successful in 1m17s
Magic link flow on contact page: customer enters email, gets a
time-limited signed link, clicks through to /orders showing all their
paid orders and full detail pages with thumbnails and product links.

- OrderLookupController generates/verifies Phoenix.Token signed links
- Contact LiveView handles lookup_orders + reset_tracking events
- Orders and OrderDetail LiveViews gated by session email
- Order detail shows thumbnails, links to products still available
- .themed-button gets base padding/font-weight so all usages are consistent
- order-summary-card sticky scoped to .cart-grid (was leaking to orders list)
- 27 new tests (1095 total)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 08:40:08 +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