Skip to content

Commit cfe6717

Browse files
authored
feat: allow odyssey_select to take a form field (#55)
1 parent 77099c4 commit cfe6717

1 file changed

Lines changed: 126 additions & 1 deletion

File tree

demo/lib/demo_web/live/odyssey_showcase_live.ex

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ defmodule DemoWeb.OdysseyShowcaseLive do
1818
"percentage" => "",
1919
"start_date" => "",
2020
"expiration_date" => "",
21-
"whitelisted_products" => ""
21+
"whitelisted_products" => "",
22+
"category_id" => "",
23+
"tag_ids" => ""
2224
}
2325

2426
socket =
@@ -30,10 +32,13 @@ defmodule DemoWeb.OdysseyShowcaseLive do
3032
|> assign(:status_selection, "Active")
3133
|> assign(:size_selection, "Medium")
3234
|> assign(:channel_selection, :email)
35+
|> assign(:standalone_select_item, nil)
3336
|> assign(:form_data, form_data)
3437
|> assign(:form, to_form(form_data, as: "form"))
3538
|> assign(:sample_activities, sample_activities())
3639
|> assign(:sample_products, sample_products())
40+
|> assign(:sample_categories, sample_categories())
41+
|> assign(:sample_tags, sample_tags())
3742

3843
{:ok, socket}
3944
end
@@ -101,6 +106,12 @@ defmodule DemoWeb.OdysseyShowcaseLive do
101106
{:noreply, socket}
102107
end
103108

109+
@impl true
110+
def handle_info({:item_selected, _context, id}, socket) do
111+
item = Enum.find(socket.assigns.sample_categories, &(to_string(&1.id) == to_string(id)))
112+
{:noreply, assign(socket, :standalone_select_item, item)}
113+
end
114+
104115
@impl true
105116
def render(assigns) do
106117
~H"""
@@ -320,6 +331,53 @@ defmodule DemoWeb.OdysseyShowcaseLive do
320331
321332
<.odyssey_divider />
322333
334+
<!-- Select Dropdown Section -->
335+
<section>
336+
<h2 class="text-2xl font-semibold mb-6">Select Dropdown</h2>
337+
<div class="space-y-4">
338+
<div>
339+
<h3 class="text-lg font-medium mb-2">Standalone Select (event-based)</h3>
340+
<p class="text-gray-600 mb-4">
341+
Fires an event when an item is selected. No form integration needed.
342+
</p>
343+
<.odyssey_select
344+
id="standalone-category-picker"
345+
items={@sample_categories}
346+
on_select={:item_selected}
347+
title="Pick a Category"
348+
color_field={:color}
349+
/>
350+
<p class="text-sm text-gray-600 mt-2">
351+
Selected: <strong>{if @standalone_select_item, do: @standalone_select_item.name, else: "None"}</strong>
352+
</p>
353+
</div>
354+
355+
<div>
356+
<h3 class="text-lg font-medium mb-2">Standalone Select with Label</h3>
357+
<.odyssey_select
358+
id="labeled-category-picker"
359+
items={@sample_categories}
360+
on_select={:item_selected}
361+
title="Pick a Category"
362+
color_field={:color}
363+
label="Category"
364+
/>
365+
</div>
366+
367+
<div>
368+
<h3 class="text-lg font-medium mb-2">Select without Colors</h3>
369+
<.odyssey_select
370+
id="no-color-picker"
371+
items={@sample_tags}
372+
on_select={:item_selected}
373+
title="Pick a Tag"
374+
/>
375+
</div>
376+
</div>
377+
</section>
378+
379+
<.odyssey_divider />
380+
323381
<!-- Navigation Section -->
324382
<section>
325383
<h2 class="text-2xl font-semibold mb-6">Navigation Components</h2>
@@ -580,6 +638,52 @@ defmodule DemoWeb.OdysseyShowcaseLive do
580638
581639
<.odyssey_divider />
582640
641+
<div>
642+
<h3 class="text-lg font-medium mb-4">Select Dropdown (Form-Integrated)</h3>
643+
<p class="text-gray-600 mb-4">
644+
The same odyssey_select component, but with a form field binding.
645+
Automatically tracks selected state and syncs with the form.
646+
</p>
647+
648+
<.form for={@form} phx-change="validate" id="select-form" class="space-y-6">
649+
<div>
650+
<h4 class="text-base font-medium mb-2">Single Select</h4>
651+
<p class="text-gray-500 text-sm mb-2">
652+
Selecting an item closes the dropdown and shows the selection in the button.
653+
</p>
654+
<.odyssey_select
655+
field={@form[:category_id]}
656+
items={@sample_categories}
657+
title="Select Category"
658+
color_field={:color}
659+
label="Category"
660+
/>
661+
<p class="text-sm text-gray-500 mt-1">
662+
Form value: <strong>{@form_data["category_id"] || "(empty)"}</strong>
663+
</p>
664+
</div>
665+
666+
<div>
667+
<h4 class="text-base font-medium mb-2">Multiple Select</h4>
668+
<p class="text-gray-500 text-sm mb-2">
669+
Clicking items toggles them on/off. Dropdown stays open for further selections.
670+
</p>
671+
<.odyssey_select
672+
field={@form[:tag_ids]}
673+
items={@sample_tags}
674+
title="Select Tags"
675+
multiple={true}
676+
label="Tags"
677+
/>
678+
<p class="text-sm text-gray-500 mt-1">
679+
Form value: <strong>{@form_data["tag_ids"] || "(empty)"}</strong>
680+
</p>
681+
</div>
682+
</.form>
683+
</div>
684+
685+
<.odyssey_divider />
686+
583687
<div>
584688
<h3 class="text-lg font-medium mb-4">Activity Picker Component</h3>
585689
<p class="text-gray-600 mb-4">
@@ -652,6 +756,27 @@ defmodule DemoWeb.OdysseyShowcaseLive do
652756
]
653757
end
654758

759+
defp sample_categories do
760+
[
761+
%{id: "cat_1", name: "Food & Drink", color: "#F59E0B"},
762+
%{id: "cat_2", name: "Outdoor Adventures", color: "#10B981"},
763+
%{id: "cat_3", name: "Arts & Culture", color: "#8B5CF6"},
764+
%{id: "cat_4", name: "Water Sports", color: "#3B82F6"},
765+
%{id: "cat_5", name: "Nightlife", color: "#EC4899"}
766+
]
767+
end
768+
769+
defp sample_tags do
770+
[
771+
%{id: "tag_1", name: "Family Friendly"},
772+
%{id: "tag_2", name: "Bestseller"},
773+
%{id: "tag_3", name: "New"},
774+
%{id: "tag_4", name: "Seasonal"},
775+
%{id: "tag_5", name: "Premium"},
776+
%{id: "tag_6", name: "Group Discount"}
777+
]
778+
end
779+
655780
defp sample_activities do
656781
[
657782
%{

0 commit comments

Comments
 (0)