Improve list view and add cookie
This commit is contained in:
@@ -30,6 +30,10 @@ topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
|
|||||||
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
|
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
|
||||||
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
|
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
|
||||||
|
|
||||||
|
window.addEventListener("toggle_view_state", e => {
|
||||||
|
document.cookie = `user_display=${e.detail.grid ? "grid" : "list"}; SameSite=lax;`
|
||||||
|
})
|
||||||
|
|
||||||
// connect if there are any LiveViews on the page
|
// connect if there are any LiveViews on the page
|
||||||
liveSocket.connect()
|
liveSocket.connect()
|
||||||
|
|
||||||
|
|||||||
16
lib/wish_web/layout.ex
Normal file
16
lib/wish_web/layout.ex
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
defmodule WishWeb.Plug.GetLayoutFromCookie do
|
||||||
|
import Plug.Conn
|
||||||
|
|
||||||
|
def init(_) do
|
||||||
|
%{}
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(conn, _opts) do
|
||||||
|
conn = fetch_cookies(conn)
|
||||||
|
|
||||||
|
case conn.cookies["user_display"] do
|
||||||
|
nil -> conn
|
||||||
|
other -> conn |> put_session(:user_display, other)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -4,19 +4,19 @@ defmodule WishWeb.HomeLive.Index do
|
|||||||
alias Wish.Wishlist
|
alias Wish.Wishlist
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(_params, _session, socket) do
|
def mount(_params, session, socket) do
|
||||||
{:ok, assign(socket, :items, Wishlist.list_items()) |> assign(:display, :grid)}
|
grid? =
|
||||||
|
case Map.get(session, "user_display", "grid") do
|
||||||
|
"grid" -> true
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, assign(socket, :items, Wishlist.list_items()) |> assign(:grid, grid?)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event("toggle", _, socket) do
|
def handle_event("toggle_view_state", _, socket) do
|
||||||
new_state =
|
{:noreply, assign(socket, :grid, !socket.assigns.grid)}
|
||||||
case socket.assigns.display do
|
|
||||||
:row -> :grid
|
|
||||||
:grid -> :row
|
|
||||||
end
|
|
||||||
|
|
||||||
{:noreply, assign(socket, :display, new_state)}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
@@ -25,7 +25,9 @@ defmodule WishWeb.HomeLive.Index do
|
|||||||
|
|
||||||
case Wishlist.toggle_received(item) do
|
case Wishlist.toggle_received(item) do
|
||||||
{:ok, updated_item} ->
|
{:ok, updated_item} ->
|
||||||
{:noreply, assign(socket, :item, updated_item)}
|
index = Enum.find_index(socket.assigns.items, &(&1.id == updated_item.id))
|
||||||
|
updated_list = List.update_at(socket.assigns.items, index, fn _ -> updated_item end)
|
||||||
|
{:noreply, assign(socket, :items, updated_list)}
|
||||||
|
|
||||||
{:error, _} ->
|
{:error, _} ->
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
|
|||||||
@@ -1,33 +1,24 @@
|
|||||||
<.header>
|
<.header>
|
||||||
Listing Items
|
Listing Items
|
||||||
<:actions>
|
<:actions>
|
||||||
<.button phx-click="toggle">
|
<.button phx-click={
|
||||||
|
JS.push("toggle_view_state")
|
||||||
|
|> JS.dispatch("toggle_view_state", detail: %{"grid" => !@grid})
|
||||||
|
}>
|
||||||
Toggle Display
|
Toggle Display
|
||||||
</.button>
|
</.button>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.header>
|
</.header>
|
||||||
|
|
||||||
<div
|
<%= if @grid do %>
|
||||||
class={
|
<div class="grid grid-cols-3 gap-2" id="items-grid">
|
||||||
case @display do
|
|
||||||
:grid -> "grid grid-cols-3 gap-2"
|
|
||||||
:row -> ""
|
|
||||||
end
|
|
||||||
}
|
|
||||||
id="items-grid"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
:for={item <- @items}
|
:for={item <- @items}
|
||||||
phx-click={JS.navigate(~p"/details/#{item}")}
|
phx-click={JS.navigate(~p"/details/#{item}")}
|
||||||
class={[
|
class="h-72 p-2 rounded hover:bg-zinc-100 active:bg-zinc-200"
|
||||||
"p-2 rounded hover:bg-zinc-100 active:bg-zinc-200",
|
,
|
||||||
case @display do
|
|
||||||
:grid -> "h-72"
|
|
||||||
:row -> "flex flex-row h-24"
|
|
||||||
end
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<div class="aspect-square flex flex-col justify-center">
|
<div class="aspect-square relative flex flex-col justify-center">
|
||||||
<img
|
<img
|
||||||
:if={item.image_url}
|
:if={item.image_url}
|
||||||
src={item.image_url}
|
src={item.image_url}
|
||||||
@@ -36,25 +27,78 @@
|
|||||||
width="224"
|
width="224"
|
||||||
class="rounded"
|
class="rounded"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<%= if item.received do %>
|
<%= if item.received do %>
|
||||||
<div class="bg-red-400 text-white">
|
<div class="bg-red-400 text-white absolute w-full h-7 bottom-0">
|
||||||
<.icon name="hero-check-circle" />Received
|
<.icon name="hero-check-circle" />Received
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
</div>
|
||||||
<div class="flex flex-row justify-between">
|
<div class="flex flex-row justify-between">
|
||||||
<%= item.title %>
|
<%= item.title %>
|
||||||
<div phx-click={JS.toggle(to: "#dropdown-#{item.id}")} class="relative">
|
<div phx-click={JS.toggle(to: "#dropdown-#{item.id}")} class="relative">
|
||||||
<.icon name="hero-ellipsis-vertical" class="w-7 h-7" />
|
<.icon name="hero-ellipsis-vertical" class="w-7 h-7" />
|
||||||
<div
|
<div
|
||||||
id={"dropdown-#{item.id}"}
|
id={"dropdown-#{item.id}"}
|
||||||
class="absolute z-10 bg-white origin-top right-0 whitespace-nowrap"
|
class="absolute z-10 w-40 bg-white origin-top right-0 whitespace-nowrap p-1 border rounded"
|
||||||
phx-click={JS.push("toggle_received", value: %{"id" => item.id})}
|
phx-click-away={JS.hide()}
|
||||||
hidden
|
hidden
|
||||||
>
|
>
|
||||||
Mark visible
|
<div
|
||||||
|
class="p-1 border border-white hover:bg-slate-100 hover:border-black select-none"
|
||||||
|
phx-click={
|
||||||
|
JS.push("toggle_received", value: %{"id" => item.id})
|
||||||
|
|> JS.hide(to: "#dropdown-#{item.id}")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Mark received
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<div class="flex flex-col space-y-4">
|
||||||
|
<div
|
||||||
|
:for={item <- @items}
|
||||||
|
class="grid grid-cols-8 grid-rows-4 h-24 p-1 border rounded"
|
||||||
|
phx-click={JS.navigate(~p"/details/#{item}")}
|
||||||
|
>
|
||||||
|
<div class="relative flex flex-col justify-center max-h-full h-full row-span-4">
|
||||||
|
<img
|
||||||
|
:if={item.image_url}
|
||||||
|
src={item.image_url}
|
||||||
|
alt={item.title}
|
||||||
|
class="max-h-full rounded"
|
||||||
|
/>
|
||||||
|
<%= if item.received do %>
|
||||||
|
<div class="absolute bg-red-400 text-xs text-white w-full h-7 bottom-0">
|
||||||
|
<.icon name="hero-check-circle" />Received
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6 row-span-4 px-2">
|
||||||
|
<%= item.title %>
|
||||||
|
</div>
|
||||||
|
<div phx-click={JS.toggle(to: "#dropdown-#{item.id}")} class="relative">
|
||||||
|
<.icon name="hero-ellipsis-vertical" class="w-7 h-7" />
|
||||||
|
<div
|
||||||
|
id={"dropdown-#{item.id}"}
|
||||||
|
class="absolute z-10 w-40 bg-white origin-top right-0 whitespace-nowrap p-1 border rounded"
|
||||||
|
phx-click-away={JS.hide()}
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="p-1 border border-white hover:bg-slate-100 hover:border-black select-none"
|
||||||
|
phx-click={
|
||||||
|
JS.push("toggle_received", value: %{"id" => item.id})
|
||||||
|
|> JS.hide(to: "#dropdown-#{item.id}")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Mark received
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -17,8 +17,12 @@ defmodule WishWeb.Router do
|
|||||||
plug :accepts, ["json"]
|
plug :accepts, ["json"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pipeline :get_layout do
|
||||||
|
plug WishWeb.Plug.GetLayoutFromCookie
|
||||||
|
end
|
||||||
|
|
||||||
scope "/", WishWeb do
|
scope "/", WishWeb do
|
||||||
pipe_through :browser
|
pipe_through [:browser, :get_layout]
|
||||||
|
|
||||||
live "/", HomeLive.Index, :index
|
live "/", HomeLive.Index, :index
|
||||||
live "/details/:id", HomeLive.Details, :index
|
live "/details/:id", HomeLive.Details, :index
|
||||||
|
|||||||
Reference in New Issue
Block a user