feat: implement header tab-based navigation

This commit is contained in:
JasterV 2026-02-09 16:33:21 +01:00
commit 10285e7bd0
10 changed files with 151 additions and 32 deletions

View file

@ -35,6 +35,11 @@ defmodule SpazioSolazzoWeb.Layouts do
default: nil, default: nil,
doc: "the current authenticated user" doc: "the current authenticated user"
attr :current_path, :string,
default: "",
required: false,
doc: "The path in the current URL"
slot :inner_block, required: true slot :inner_block, required: true
def app(assigns) do def app(assigns) do
@ -53,11 +58,53 @@ defmodule SpazioSolazzoWeb.Layouts do
<ul class="menu menu-horizontal px-1"> <ul class="menu menu-horizontal px-1">
<%= if @current_user && @current_user.is_admin do %> <%= if @current_user && @current_user.is_admin do %>
<li> <li>
<.link class="dark:hover:bg-secondary/20" navigate={~p"/admin/dashboard"}> <.link
class={[
"dark:hover:bg-secondary/20",
String.starts_with?(@current_path, "/admin") &&
"bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
navigate={~p"/admin/dashboard"}
>
Dashboard Dashboard
</.link> </.link>
</li> </li>
<% end %> <% end %>
<li>
<.link
class={[
"dark:hover:bg-secondary/20",
@current_path == "/arcipelago" && "bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
navigate={~p"/arcipelago"}
>
Arcipelago
</.link>
</li>
<li>
<.link
class={[
"dark:hover:bg-secondary/20",
@current_path == "/media-room" && "bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
navigate={~p"/media-room"}
>
Media Room
</.link>
</li>
<li>
<.link
class={[
"dark:hover:bg-secondary/20",
@current_path == "/hall" && "bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
navigate={~p"/hall"}
>
Hall
</.link>
</li>
</ul> </ul>
</div> </div>
<div class="navbar-end flex gap-3"> <div class="navbar-end flex gap-3">
@ -81,8 +128,10 @@ defmodule SpazioSolazzoWeb.Layouts do
<% end %> <% end %>
<%!-- Mobile menu --%> <%!-- Mobile menu --%>
<%= if @current_user do %> <div class={[
<div class="dropdown dropdown-end"> "dropdown dropdown-end",
@current_user == nil && "md:hidden"
]}>
<div <div
tabindex="0" tabindex="0"
role="button" role="button"
@ -94,16 +143,65 @@ defmodule SpazioSolazzoWeb.Layouts do
tabindex="-1" tabindex="-1"
class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow dark:shadow-none dark:border dark:border-white/40 bg-base-100 rounded-box w-52" class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow dark:shadow-none dark:border dark:border-white/40 bg-base-100 rounded-box w-52"
> >
<%= if @current_user && @current_user.is_admin do %>
<li class="md:hidden"> <li class="md:hidden">
<.link navigate={~p"/admin/dashboard"}> <.link
navigate={~p"/arcipelago"}
class={[
"dark:hover:bg-secondary/20",
@current_path == "/arcipelago" && "bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
>
<.icon name="hero-briefcase" class="size-4" /> Arcipelago
</.link>
</li>
<li class="md:hidden">
<.link
navigate={~p"/media-room"}
class={[
"dark:hover:bg-secondary/20",
@current_path == "/media-room" && "bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
>
<.icon name="hero-computer-desktop" class="size-4" /> Media Room
</.link>
</li>
<li class="md:hidden">
<.link
navigate={~p"/hall"}
class={[
"dark:hover:bg-secondary/20",
@current_path == "/hall" && "bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
>
<.icon name="hero-musical-note" class="size-4" /> Hall
</.link>
</li>
<%= if @current_user do %>
<%= if @current_user.is_admin do %>
<li class="md:hidden">
<.link
navigate={~p"/admin/dashboard"}
class={[
"dark:hover:bg-secondary/20",
String.starts_with?(@current_path, "/admin") &&
"bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
>
<.icon name="hero-squares-2x2" class="size-4" /> Dashboard <.icon name="hero-squares-2x2" class="size-4" /> Dashboard
</.link> </.link>
</li> </li>
<% end %> <% end %>
<li class="md:hidden"> <li class="md:hidden">
<.link navigate={~p"/profile"}> <.link
navigate={~p"/profile"}
class={[
"dark:hover:bg-secondary/20",
@current_path == "/profile" && "bg-base-200 dark:bg-secondary/20 dark:text-white"
]}
>
<.icon name="hero-user" class="size-4" /> Profile <.icon name="hero-user" class="size-4" /> Profile
</.link> </.link>
</li> </li>
@ -112,9 +210,9 @@ defmodule SpazioSolazzoWeb.Layouts do
<.icon name="hero-arrow-right-on-rectangle" class="size-4" /> Sign Out <.icon name="hero-arrow-right-on-rectangle" class="size-4" /> Sign Out
</.link> </.link>
</li> </li>
<% end %>
</ul> </ul>
</div> </div>
<% end %>
</div> </div>
</header> </header>

View file

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_user={@current_user}> <Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<main class="flex-grow px-4 py-8 md:px-8"> <main class="flex-grow px-4 py-8 md:px-8">
<div class="max-w-6xl mx-auto flex flex-col gap-8"> <div class="max-w-6xl mx-auto flex flex-col gap-8">
<.back_to_link <.back_to_link

View file

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_user={@current_user}> <Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<main class="flex-grow px-4 py-8 md:px-8"> <main class="flex-grow px-4 py-8 md:px-8">
<div class="max-w-6xl mx-auto"> <div class="max-w-6xl mx-auto">
<div class="mb-12 text-center"> <div class="mb-12 text-center">

View file

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_user={@current_user}> <Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<main class="flex-1"> <main class="flex-1">
<section class="mx-auto max-w-[1000px] px-6 py-10"> <section class="mx-auto max-w-[1000px] px-6 py-10">
<.back_to_link <.back_to_link

View file

@ -0,0 +1,17 @@
defmodule SpazioSolazzoWeb.AssignPathHook do
@moduledoc """
Attach a `handle_params` hook on any live view that injects the current path from the URL into the socket assigns
"""
import Phoenix.Component
import Phoenix.LiveView
def on_mount(:default, _params, _session, socket) do
{:cont, attach_hook(socket, :set_current_path, :handle_params, &handle_path_update/3)}
end
defp handle_path_update(_params, url, socket) do
%{path: path} = URI.parse(url)
{:cont, assign(socket, :current_path, path)}
end
end

View file

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_user={@current_user}> <Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<.page_header <.page_header
booking_path={~p"/book/space/#{@space.slug}"} booking_path={~p"/book/space/#{@space.slug}"}
booking_label="Request a desk" booking_label="Request a desk"

View file

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_user={@current_user}> <Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<.page_header <.page_header
booking_path={~p"/book/space/#{@space.slug}"} booking_path={~p"/book/space/#{@space.slug}"}
booking_label="Booking request" booking_label="Booking request"

View file

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_user={@current_user}> <Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<.page_header <.page_header
booking_path={~p"/book/space/#{@space.slug}"} booking_path={~p"/book/space/#{@space.slug}"}
booking_label="Booking request" booking_label="Booking request"

View file

@ -1,4 +1,4 @@
<Layouts.app flash={@flash} current_user={@current_user}> <Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<div class="mx-auto max-w-[800px] px-6 py-12"> <div class="mx-auto max-w-[800px] px-6 py-12">
<.back_to_link <.back_to_link
navigate={~p"/"} navigate={~p"/"}

View file

@ -31,7 +31,8 @@ defmodule SpazioSolazzoWeb.Router do
ash_authentication_live_session :unauthenticated_routes, ash_authentication_live_session :unauthenticated_routes,
on_mount: [ on_mount: [
{SpazioSolazzoWeb.LiveUserAuth, :live_user_optional} {SpazioSolazzoWeb.LiveUserAuth, :live_user_optional},
SpazioSolazzoWeb.AssignPathHook
] do ] do
live "/", PageLive live "/", PageLive
live "/arcipelago", CoworkingLive live "/arcipelago", CoworkingLive
@ -41,7 +42,8 @@ defmodule SpazioSolazzoWeb.Router do
ash_authentication_live_session :no_user_routes, ash_authentication_live_session :no_user_routes,
on_mount: [ on_mount: [
{SpazioSolazzoWeb.LiveUserAuth, :live_no_user} {SpazioSolazzoWeb.LiveUserAuth, :live_no_user},
SpazioSolazzoWeb.AssignPathHook
] do ] do
live "/sign-in/callback", AuthCallbackLive live "/sign-in/callback", AuthCallbackLive
live "/sign-in", SignInLive live "/sign-in", SignInLive
@ -49,7 +51,8 @@ defmodule SpazioSolazzoWeb.Router do
ash_authentication_live_session :authenticated_routes, ash_authentication_live_session :authenticated_routes,
on_mount: [ on_mount: [
{SpazioSolazzoWeb.LiveUserAuth, :live_user_required} {SpazioSolazzoWeb.LiveUserAuth, :live_user_required},
SpazioSolazzoWeb.AssignPathHook
] do ] do
live "/book/space/:space_slug", SpaceBookingLive live "/book/space/:space_slug", SpaceBookingLive
live "/bookings/cancel", BookingCancellationLive live "/bookings/cancel", BookingCancellationLive
@ -58,7 +61,8 @@ defmodule SpazioSolazzoWeb.Router do
ash_authentication_live_session :admin_routes, ash_authentication_live_session :admin_routes,
on_mount: [ on_mount: [
{SpazioSolazzoWeb.LiveUserAuth, :live_admin_required} {SpazioSolazzoWeb.LiveUserAuth, :live_admin_required},
SpazioSolazzoWeb.AssignPathHook
] do ] do
live "/admin/dashboard", Admin.DashboardLive live "/admin/dashboard", Admin.DashboardLive
live "/admin/bookings", Admin.BookingManagementLive live "/admin/bookings", Admin.BookingManagementLive