Skip to main content

max / makenotwork

6.5 KB · 123 lines History Blame Raw
1 {% extends "base.html" %}
2
3 {% block title %}Discover - Makenotwork{% endblock %}
4 {% block body_attrs %} class="{{ crate::shell::measure(crate::shell::Measure::Wide) }}"{% endblock %}
5
6 {% block content %}
7 {% include "partials/site_header.html" %}
8
9 <h1 class="page-title">Discover</h1>
10
11 <div class="discover-layout{% if mode == "projects" && sidebar.category_filters.is_empty() %} no-sidebar{% endif %}">
12 {% include "partials/discover_sidebar.html" %}
13
14 <button type="button" class="discover-filter-toggle" data-action="toggleDiscoverFilters" aria-expanded="false" aria-controls="discover-sidebar" aria-label="Toggle filters">
15 Filters{% if sidebar.active_filter_count > 0 %} <span class="filter-count">{{ sidebar.active_filter_count }}</span>{% endif %}
16 </button>
17
18 <main class="discover-main">
19 <div class="mode-toggle">
20 <button class="toggle-btn{% if mode == "items" %} is-selected{% endif %}"
21 hx-get="/discover"
22 hx-target="body"
23 hx-push-url="true"
24 hx-vals='{"mode": "items"}'>Items</button>
25 <button class="toggle-btn{% if mode == "projects" %} is-selected{% endif %}"
26 hx-get="/discover"
27 hx-target="body"
28 hx-push-url="true"
29 hx-vals='{"mode": "projects"}'>Projects</button>
30 <div class="view-controls">
31 <button type="button" class="view-btn" data-view="list" title="List view">|||</button>
32 <button type="button" class="view-btn is-selected" data-view="grid" title="Grid view">:::</button>
33 </div>
34 </div>
35
36 {# `tag-added` is fired by the typeahead once it appends a hidden
37 input, so picking a suggestion refreshes results through the same
38 path as every other filter control.
39
40 `#q` beside `.discover-filter` in every include on this screen:
41 the search box is a described Field now and carries the classes
42 its renderer writes, not one this repo chose. Its id is the
43 field's own name, which is the handle the description already
44 had. Every control that re-reads the results needs the search
45 value along, and a class on markup nobody here writes is not
46 something to reach for. #}
47 <form id="discover-form" action="/discover" method="get"
48 hx-get="/discover/results"
49 hx-target="#results-container" hx-swap="outerHTML"
50 hx-indicator="#search-spinner"
51 hx-include=".discover-filter, #q"
52 hx-trigger="tag-added">
53 <input type="hidden" id="mode-input" name="mode" value="{{ mode }}" class="discover-filter">
54 <div class="table-controls">
55 {# Described (N8): the box, the list it owns, the route it
56 asks for candidates, the two waits, the floor, the
57 filters that ride with the results question and the page
58 picking a row goes to all come out of crate::quasi. What
59 stood here was a bare input and an empty list pointed at
60 each other by id, with the rest in page-discover.js.
61
62 The wrapper stays: it is the positioning context the
63 list is drawn against, and the flex child the toolbar
64 row sizes. #}
65 <div class="search-wrapper">
66 {{ crate::quasi::discover_search::search_box(mode, search_query)|safe }}
67 </div>
68 <span id="search-spinner" class="htmx-indicator" aria-live="polite">Searching...</span>
69 <span class="table-meta" id="total-count">{{ count_label }}</span>
70 <label for="sort-select" class="sr-only">Sort by</label>
71 <select class="sort-select discover-filter"
72 id="sort-select"
73 name="sort"
74 aria-label="Sort results by"
75 hx-get="/discover/results"
76 hx-trigger="change"
77 hx-target="#results-container" hx-swap="outerHTML"
78 hx-indicator="#search-spinner"
79 hx-include=".discover-filter, #q">
80 {% if mode == "projects" %}
81 <option value="newest"{% if sort_by == "newest" || sort_by == "" %} selected{% endif %}>Newest</option>
82 <option value="most_sold"{% if sort_by == "most_sold" %} selected{% endif %}>Most items</option>
83 {% else %}
84 <option value="most_sold"{% if sort_by == "most_sold" %} selected{% endif %}>Most sold</option>
85 <option value="newest"{% if sort_by == "newest" || sort_by == "" %} selected{% endif %}>Newest</option>
86 <option value="price_asc"{% if sort_by == "price_asc" %} selected{% endif %}>Price asc</option>
87 <option value="price_desc"{% if sort_by == "price_desc" %} selected{% endif %}>Price desc</option>
88 {% endif %}
89 </select>
90 </div>
91 </form>
92
93 {% if mode == "projects" %}
94 <div class="table-header projects-header">
95 <span>Name</span>
96 <span>Category</span>
97 <span class="col-right">Items</span>
98 <span class="col-right">Added</span>
99 </div>
100 {% else %}
101 <div class="table-header">
102 <span>Type</span>
103 <span>Name</span>
104 <span>Tag</span>
105 <span class="col-right">Price</span>
106 <span class="col-right">Added</span>
107 </div>
108 {% endif %}
109
110 {# The region is the partial's own root now, not a wrapper here:
111 every control that re-reads it swaps the element whole
112 (hx-swap="outerHTML"), which is what a described control emits and
113 what stops the region losing its id on the first pick. #}
114 {% include "partials/discover_results.html" %}
115 </main>
116 </div>
117 {% endblock %}
118
119 {% block scripts %}
120 <script src="/static/collections.js?v=0514"></script>
121 <script src="/static/page-discover.js?v=0624" defer></script>
122 {% endblock %}
123