add FTS5 full-text product search

Adds SQLite FTS5 search index with BM25 ranking across product title,
category, variant attributes, and description. Search modal now has
live results with thumbnails, prices, and click-to-navigate. Index
rebuilds automatically after each provider sync.

Also fixes Access syntax on Product/ProductImage structs (Map.get
instead of bracket notation) which was causing crashes when real
products were loaded from the database.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-13 07:29:19 +00:00
parent 35e0386abb
commit 037cd168cd
19 changed files with 603 additions and 34 deletions

View File

@@ -101,6 +101,8 @@ defmodule SimpleshopThemeWeb.Shop.Collection do
cart_drawer_open={@cart_drawer_open}
cart_status={assigns[:cart_status]}
active_page="collection"
search_query={assigns[:search_query] || ""}
search_results={assigns[:search_results] || []}
>
<main id="main-content">
<.collection_header

View File

@@ -20,14 +20,14 @@ defmodule SimpleshopThemeWeb.Shop.ProductShow do
# Build gallery images from local image_id or external URL
gallery_images =
(product[:images] || [])
(Map.get(product, :images) || [])
|> Enum.sort_by(& &1.position)
|> Enum.map(fn img -> ProductImage.direct_url(img, 1200) end)
|> Enum.reject(&is_nil/1)
# Initialize variant selection
option_types = Product.option_types(product)
variants = product[:variants] || []
variants = Map.get(product, :variants) || []
{selected_options, selected_variant} = initialize_variant_selection(variants)
available_options = compute_available_options(option_types, variants, selected_options)
display_price = variant_price(selected_variant, product)