diff --git a/app/templates/shared/macros/shop/breadcrumbs.html b/app/templates/shared/macros/shop/breadcrumbs.html new file mode 100644 index 00000000..0f37893f --- /dev/null +++ b/app/templates/shared/macros/shop/breadcrumbs.html @@ -0,0 +1,262 @@ +{# + Breadcrumbs Components + ====================== + Navigation breadcrumb trail for shop pages. + + Usage: + {% from 'shared/macros/shop/breadcrumbs.html' import shop_breadcrumbs, auto_breadcrumbs %} +#} + + +{# + Shop Breadcrumbs + ================ + Breadcrumb navigation trail. + + Parameters: + - items: List of breadcrumb items (static) + - items_var: Alpine.js expression for items (dynamic) + - separator: Separator icon (default: 'chevron-right') + - show_home: Show home link (default: true) + - home_url: URL for home (default: '/') + - home_label: Label for home (default: 'Home') + + Item structure: + { + label: 'Category Name', + url: '/category/...', // Optional, last item typically has no URL + icon: 'folder' // Optional icon + } + + Usage (static): + {{ shop_breadcrumbs(items=[ + {'label': 'Electronics', 'url': '/category/electronics'}, + {'label': 'Headphones', 'url': '/category/headphones'}, + {'label': 'Wireless'} + ]) }} + + Usage (dynamic): + {{ shop_breadcrumbs(items_var='breadcrumbs') }} +#} +{% macro shop_breadcrumbs( + items=none, + items_var=none, + separator='chevron-right', + show_home=true, + home_url='/', + home_label='Home' +) %} + +{% endmacro %} + + +{# + Auto Breadcrumbs + ================ + Automatically generates breadcrumbs from category hierarchy. + + Parameters: + - product_var: Alpine.js expression for product (optional) + - category_var: Alpine.js expression for current category + - show_home: Show home link (default: true) + + Usage: + {{ auto_breadcrumbs(category_var='currentCategory') }} + {{ auto_breadcrumbs(product_var='product') }} +#} +{% macro auto_breadcrumbs( + product_var=none, + category_var='currentCategory', + show_home=true +) %} + +{% endmacro %} + + +{# + Compact Breadcrumbs + =================== + Mobile-friendly breadcrumbs showing only parent and current. + + Parameters: + - parent: Parent item (static) + - parent_var: Alpine.js expression for parent + - current: Current page label + - current_var: Alpine.js expression for current + + Usage: + {{ compact_breadcrumbs(parent={'label': 'Electronics', 'url': '/electronics'}, current='Headphones') }} +#} +{% macro compact_breadcrumbs( + parent=none, + parent_var=none, + current=none, + current_var=none +) %} + +{% endmacro %} diff --git a/app/templates/shared/macros/shop/category-nav.html b/app/templates/shared/macros/shop/category-nav.html new file mode 100644 index 00000000..4ece2441 --- /dev/null +++ b/app/templates/shared/macros/shop/category-nav.html @@ -0,0 +1,391 @@ +{# + Category Navigation Components + ============================== + Category browsing sidebar and menu for shop navigation. + + Usage: + {% from 'shared/macros/shop/category-nav.html' import category_nav, category_tree, category_menu %} +#} + + +{# + Category Navigation + =================== + Sidebar category navigation with nested categories. + + Parameters: + - categories_var: Alpine.js expression for categories array (default: 'categories') + - current_var: Alpine.js expression for current category (default: 'currentCategory') + - show_count: Show product counts (default: true) + - collapsible: Make nested categories collapsible (default: true) + - max_depth: Maximum nesting depth to show (default: 3) + + Expected category object: + { + id: 1, + name: 'Electronics', + slug: 'electronics', + url: '/category/electronics', + product_count: 150, + children: [...] + } + + Usage: + {{ category_nav(categories_var='categories', show_count=true) }} +#} +{% macro category_nav( + categories_var='categories', + current_var='currentCategory', + show_count=true, + collapsible=true, + max_depth=3 +) %} + +{% endmacro %} + + +{# + Internal: Category Item (recursive) +#} +{% macro _category_item(current_var, show_count, collapsible, depth, max_depth) %} +
+
+ {# Category Link #} + + + {% if show_count %} + + {% endif %} + + + {# Expand/Collapse Button #} + {% if collapsible %} + + {% endif %} +
+ + {# Nested Categories #} + {% if depth < max_depth - 1 %} +
+ +
+ {% endif %} +
+{% endmacro %} + + +{# + Category Tree (Flat List) + ========================= + Simple flat list of categories without nesting. + + Parameters: + - categories_var: Alpine.js expression for categories + - current_var: Alpine.js expression for current category + - show_count: Show product counts (default: true) + - layout: 'vertical' | 'horizontal' (default: 'vertical') + + Usage: + {{ category_tree(categories_var='topCategories', layout='horizontal') }} +#} +{% macro category_tree( + categories_var='categories', + current_var='currentCategory', + show_count=true, + layout='vertical' +) %} + +{% endmacro %} + + +{# + Category Menu (Dropdown/Mega Menu) + ================================== + Horizontal category menu for header navigation. + + Parameters: + - categories_var: Alpine.js expression for categories + - show_all_link: Show "All Categories" link (default: true) + - all_link_url: URL for all categories (default: '/categories') + + Usage: + {{ category_menu(categories_var='mainCategories') }} +#} +{% macro category_menu( + categories_var='categories', + show_all_link=true, + all_link_url='/categories' +) %} + +{% endmacro %} + + +{# + Mobile Category Drawer + ====================== + Full-screen category navigation for mobile devices. + + Parameters: + - categories_var: Alpine.js expression for categories + - show_var: Alpine.js variable for drawer visibility (default: 'showCategoryDrawer') + + Usage: + {{ category_drawer(categories_var='categories', show_var='showCategoryDrawer') }} +#} +{% macro category_drawer( + categories_var='categories', + show_var='showCategoryDrawer' +) %} + +{% endmacro %} diff --git a/app/templates/shared/macros/shop/filter-sidebar.html b/app/templates/shared/macros/shop/filter-sidebar.html new file mode 100644 index 00000000..bbf0eaee --- /dev/null +++ b/app/templates/shared/macros/shop/filter-sidebar.html @@ -0,0 +1,786 @@ +{# + Filter Sidebar Components + ========================= + Product filtering panel for category and search pages. + + Usage: + {% from 'shared/macros/shop/filter-sidebar.html' import filter_sidebar, filter_group, price_filter, rating_filter %} +#} + + +{# + Filter Sidebar + ============== + Complete filter sidebar with multiple filter types. + + Parameters: + - filters_var: Alpine.js expression for filter configuration (default: 'filters') + - active_filters_var: Alpine.js expression for active filters (default: 'activeFilters') + - on_change: JavaScript callback when filters change (default: 'filterProducts()') + - show_clear: Show clear all button (default: true) + - collapsible: Make filter groups collapsible (default: true) + + Expected filters structure: + { + categories: [{ id, name, count }], + brands: [{ id, name, count }], + priceRange: { min: 0, max: 1000 }, + attributes: { + color: [{ value, label, count, hex }], + size: [{ value, label, count }] + }, + ratings: [{ value: 5, count: 10 }, ...] + } + + Usage: + {{ filter_sidebar(filters_var='filters', on_change='applyFilters()') }} +#} +{% macro filter_sidebar( + filters_var='filters', + active_filters_var='activeFilters', + on_change='filterProducts()', + show_clear=true, + collapsible=true +) %} + +{% endmacro %} + + +{# + Internal: Filter Group for Categories/Brands +#} +{% macro _filter_group(title, type, collapsible) %} +
+ {% if collapsible %} + + {% else %} +

{{ title }}

+ {% endif %} + +
+ +
+
+{% endmacro %} + + +{# + Internal: Price Range Group +#} +{% macro _price_range_group(filters_var, active_filters_var, on_change, collapsible) %} +
+ {% if collapsible %} + + {% else %} +

Price Range

+ {% endif %} + +
+ {# Dual Range Slider #} +
+
+
+
+ + +
+ + {# Price Inputs #} +
+
+ +
+ $ + +
+
+ - +
+ +
+ $ + +
+
+
+
+
+{% endmacro %} + + +{# + Internal: Rating Group +#} +{% macro _rating_group(filters_var, active_filters_var, on_change, collapsible) %} +
+ {% if collapsible %} + + {% else %} +

Rating

+ {% endif %} + +
+ + +
+
+{% endmacro %} + + +{# + Internal: Dynamic Attribute Group (color, size, etc.) +#} +{% macro _attribute_group(filters_var, active_filters_var, on_change, collapsible) %} +
+ {% if collapsible %} + + {% else %} +

+ {% endif %} + +
+ {# Color Swatches #} + + + {# Size/Other Buttons #} + + + {# Checkbox List for other attributes #} + +
+
+{% endmacro %} + + +{# + Price Filter (Standalone) + ========================= + Standalone price range filter component. + + Parameters: + - min: Minimum price (default: 0) + - max: Maximum price (default: 1000) + - value_min_var: Alpine.js var for min value (default: 'priceMin') + - value_max_var: Alpine.js var for max value (default: 'priceMax') + - on_change: Callback on change (default: 'updateFilters()') + - currency: Currency symbol (default: '$') + + Usage: + {{ price_filter(min=0, max=500, on_change='filterByPrice()') }} +#} +{% macro price_filter( + min=0, + max=1000, + value_min_var='priceMin', + value_max_var='priceMax', + on_change='updateFilters()', + currency='$' +) %} +
+
+
+
+ {{ currency }} + +
+
+ to +
+
+ {{ currency }} + +
+
+
+
+{% endmacro %} + + +{# + Rating Filter (Standalone) + ========================== + Standalone star rating filter. + + Parameters: + - value_var: Alpine.js var for selected rating (default: 'minRating') + - on_change: Callback on change (default: 'updateFilters()') + - show_count: Show product counts (default: false) + - counts: List of counts per rating level + + Usage: + {{ rating_filter(value_var='minRating', on_change='filterByRating()') }} +#} +{% macro rating_filter( + value_var='minRating', + on_change='updateFilters()', + show_count=false, + counts=none +) %} +
+ {% for i in range(5, 0, -1) %} + + {% endfor %} +
+{% endmacro %} + + +{# + Mobile Filter Drawer + ==================== + Full-screen filter panel for mobile devices. + + Parameters: + - show_var: Alpine.js variable for visibility (default: 'showFilters') + - filters_var: Alpine.js expression for filters (default: 'filters') + - active_filters_var: Alpine.js expression for active filters (default: 'activeFilters') + - on_apply: Callback on apply (default: 'applyFilters()') + - result_count_var: Alpine.js var showing result count (default: 'productCount') + + Usage: + {{ mobile_filter_drawer(show_var='showMobileFilters') }} +#} +{% macro mobile_filter_drawer( + show_var='showFilters', + filters_var='filters', + active_filters_var='activeFilters', + on_apply='applyFilters()', + result_count_var='productCount' +) %} + +{% endmacro %} + + +{# + Filter Trigger Button + ==================== + Button to open mobile filter drawer. + + Parameters: + - show_var: Alpine.js variable to toggle (default: 'showFilters') + - active_count_var: Alpine.js var for active filter count (default: none) + + Usage: + {{ filter_trigger(show_var='showMobileFilters') }} +#} +{% macro filter_trigger( + show_var='showFilters', + active_count_var=none +) %} + +{% endmacro %} + + +{# + Sort Dropdown + ============= + Product sorting dropdown. + + Parameters: + - value_var: Alpine.js var for sort value (default: 'sortBy') + - options: Sort options list (default: common options) + - on_change: Callback on change (default: 'sortProducts()') + + Usage: + {{ sort_dropdown(value_var='currentSort') }} +#} +{% macro sort_dropdown( + value_var='sortBy', + options=none, + on_change='sortProducts()' +) %} +{% set default_options = [ + {'value': 'relevance', 'label': 'Relevance'}, + {'value': 'price_asc', 'label': 'Price: Low to High'}, + {'value': 'price_desc', 'label': 'Price: High to Low'}, + {'value': 'newest', 'label': 'Newest First'}, + {'value': 'rating', 'label': 'Highest Rated'}, + {'value': 'popular', 'label': 'Most Popular'} +] %} +{% set sort_options = options if options else default_options %} +
+ + + +
+{% endmacro %} diff --git a/app/templates/shared/macros/shop/search-bar.html b/app/templates/shared/macros/shop/search-bar.html new file mode 100644 index 00000000..a8a3fdb3 --- /dev/null +++ b/app/templates/shared/macros/shop/search-bar.html @@ -0,0 +1,627 @@ +{# + Search Bar Components + ===================== + Product search with autocomplete and suggestions for shop pages. + + Usage: + {% from 'shared/macros/shop/search-bar.html' import search_bar, search_autocomplete, mobile_search %} +#} + + +{# + Search Bar + ========== + Basic search input with icon and optional button. + + Parameters: + - placeholder: Placeholder text (default: 'Search products...') + - action: Form action URL (default: '/search') + - method: Form method (default: 'get') + - name: Input name (default: 'q') + - value: Initial value (default: '') + - show_button: Show search button (default: false) + - button_label: Button text (default: 'Search') + - size: 'sm' | 'md' | 'lg' (default: 'md') + - variant: 'default' | 'filled' | 'minimal' (default: 'default') + + Usage: + {{ search_bar(placeholder='Search for products...') }} + {{ search_bar(show_button=true, size='lg') }} +#} +{% macro search_bar( + placeholder='Search products...', + action='/search', + method='get', + name='q', + value='', + show_button=false, + button_label='Search', + size='md', + variant='default' +) %} +{% set sizes = { + 'sm': {'input': 'py-1.5 pl-8 pr-3 text-sm', 'icon': 'w-4 h-4 left-2.5', 'button': 'px-3 py-1.5 text-sm'}, + 'md': {'input': 'py-2.5 pl-10 pr-4 text-sm', 'icon': 'w-5 h-5 left-3', 'button': 'px-4 py-2.5 text-sm'}, + 'lg': {'input': 'py-3 pl-12 pr-4 text-base', 'icon': 'w-6 h-6 left-3.5', 'button': 'px-5 py-3 text-base'} +} %} +{% set variants = { + 'default': 'bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 focus:border-purple-500 dark:focus:border-purple-400 focus:ring-2 focus:ring-purple-500/20', + 'filled': 'bg-gray-100 dark:bg-gray-700 border border-transparent focus:bg-white dark:focus:bg-gray-800 focus:border-purple-500 dark:focus:border-purple-400 focus:ring-2 focus:ring-purple-500/20', + 'minimal': 'bg-transparent border-b border-gray-300 dark:border-gray-600 rounded-none focus:border-purple-500 dark:focus:border-purple-400' +} %} +
+
+ + + + +
+ {% if show_button %} + + {% endif %} +
+{% endmacro %} + + +{# + Search Autocomplete + =================== + Search input with dropdown suggestions and autocomplete. + + Parameters: + - placeholder: Placeholder text (default: 'Search products...') + - action: Form action URL (default: '/search') + - search_endpoint: API endpoint for suggestions (default: '/api/search/suggest') + - min_chars: Minimum characters to trigger search (default: 2) + - debounce: Debounce delay in ms (default: 300) + - show_recent: Show recent searches (default: true) + - show_popular: Show popular searches (default: true) + - max_suggestions: Maximum suggestions to show (default: 5) + - size: 'sm' | 'md' | 'lg' (default: 'md') + + Usage: + {{ search_autocomplete(search_endpoint='/api/products/search') }} +#} +{% macro search_autocomplete( + placeholder='Search products...', + action='/search', + search_endpoint='/api/search/suggest', + min_chars=2, + debounce=300, + show_recent=true, + show_popular=true, + max_suggestions=5, + size='md' +) %} +{% set sizes = { + 'sm': {'input': 'py-1.5 pl-8 pr-8 text-sm', 'icon': 'w-4 h-4', 'dropdown': 'mt-1'}, + 'md': {'input': 'py-2.5 pl-10 pr-10 text-sm', 'icon': 'w-5 h-5', 'dropdown': 'mt-2'}, + 'lg': {'input': 'py-3 pl-12 pr-12 text-base', 'icon': 'w-6 h-6', 'dropdown': 'mt-2'} +} %} +
+
+
+ + + + + + + + +
+
+ + {# Dropdown #} + +
+{% endmacro %} + + +{# + Mobile Search + ============= + Full-screen search overlay for mobile devices. + + Parameters: + - show_var: Alpine.js variable for visibility (default: 'showMobileSearch') + - placeholder: Placeholder text (default: 'Search products...') + - action: Form action URL (default: '/search') + - search_endpoint: API endpoint for suggestions (default: '/api/search/suggest') + + Usage: + {{ mobile_search(show_var='showSearch') }} +#} +{% macro mobile_search( + show_var='showMobileSearch', + placeholder='Search products...', + action='/search', + search_endpoint='/api/search/suggest' +) %} + +{% endmacro %} + + +{# + Search Trigger Button + ==================== + Button to open mobile search or focus desktop search. + + Parameters: + - show_var: Alpine.js variable to toggle (default: 'showMobileSearch') + - sr_label: Screen reader label (default: 'Open search') + + Usage: + {{ search_trigger(show_var='showSearch') }} +#} +{% macro search_trigger( + show_var='showMobileSearch', + sr_label='Open search' +) %} + +{% endmacro %} + + +{# + Instant Search Results + ===================== + Inline search results component (for header search). + + Parameters: + - results_var: Alpine.js expression for search results (default: 'searchResults') + - loading_var: Alpine.js expression for loading state (default: 'isSearching') + - query_var: Alpine.js expression for search query (default: 'searchQuery') + - show_var: Alpine.js expression for visibility (default: 'showResults') + + Usage: + {{ instant_search_results(results_var='searchResults') }} +#} +{% macro instant_search_results( + results_var='searchResults', + loading_var='isSearching', + query_var='searchQuery', + show_var='showResults' +) %} + +{% endmacro %}