cover/Elixir.DaProductAppWeb.SidebarComponent.html

1
:-(
defmodule DaProductAppWeb.SidebarComponent do
2 @moduledoc """
3 Sidebar LiveComponent for navigation menu
4 """
5
:-(
use DaProductAppWeb, :live_component
6
7 @impl true
8 def render(assigns) do
9
:-(
~H"""
10 <aside class="min-h-full w-64 bg-base-200 text-base-content">
11 <!-- Logo Section -->
12 <div class="flex h-16 items-center justify-center border-b border-base-300 bg-base-100">
13 <div class="flex items-center space-x-2">
14 <div class="w-8 h-8 bg-primary rounded-lg flex items-center justify-center">
15 <svg class="w-5 h-5 text-primary-content" fill="currentColor" viewBox="0 0 20 20">
16 <path d="M4 4a2 2 0 00-2 2v1h16V6a2 2 0 00-2-2H4zM18 9H2v5a2 2 0 002 2h12a2 2 0 002-2V9zM4 13a1 1 0 011-1h1a1 1 0 110 2H5a1 1 0 01-1-1zm5-1a1 1 0 100 2h1a1 1 0 100-2H9z"></path>
17 </svg>
18 </div>
19 <span class="text-lg font-bold text-base-content">Mercury UPI</span>
20 </div>
21 </div>
22
23 <!-- Navigation Menu -->
24 <div class="p-4">
25 <nav class="space-y-2">
26
:-(
<%= for menu_item <- @menu_items do %>
27
:-(
<.nav_link
28
:-(
href={menu_item.path}
29
:-(
active={@current_page == menu_item.key}
30
:-(
icon={menu_item.icon}
31 >
32
:-(
<%= menu_item.label %>
33 </.nav_link>
34 <% end %>
35 </nav>
36 </div>
37
38 <!-- User Profile Section at Bottom -->
39 <div class="absolute bottom-0 left-0 right-0 p-4 border-t border-base-300 bg-base-100">
40 <div class="flex items-center space-x-3">
41 <div class="avatar">
42 <div class="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center">
43 <span class="text-sm font-medium text-primary">
44
:-(
<%= String.first(@current_user.name || "U") %>
45 </span>
46 </div>
47 </div>
48 <div class="flex-1 min-w-0">
49 <p class="text-sm font-medium text-base-content truncate">
50
:-(
<%= @current_user.name || "User" %>
51 </p>
52 <p class="text-xs text-base-content/70 truncate">
53
:-(
<%= @current_user.role.name || "user" %>
54 </p>
55 </div>
56 <div class="dropdown dropdown-top dropdown-end">
57 <label tabindex="0" class="btn btn-ghost btn-xs">
58 <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
59 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"></path>
60 </svg>
61 </label>
62 <ul tabindex="0" class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-32">
63 <li><a href="#" class="text-xs">Profile</a></li>
64 <li><a href="#" class="text-xs">Settings</a></li>
65
:-(
<li><a href={~p"/logout"} data-method="delete" class="text-xs">Logout</a></li>
66 </ul>
67 </div>
68 </div>
69 </div>
70 </aside>
71 """
72 end
73
74 @impl true
75
:-(
def update(assigns, socket) do
76 # Get menu items based on current user's role
77
:-(
menu_items = DaProductAppWeb.MenuManager.get_menu_items(assigns.current_user)
78
79
:-(
socket =
80 socket
81 |> assign(assigns)
82 |> assign(:menu_items, menu_items)
83
84 {:ok, socket}
85 end
86
87 # Private function components
88 defp nav_link(assigns) do
89
:-(
assigns = assign_new(assigns, :mobile, fn -> false end)
90
91
:-(
~H"""
92
:-(
<a href={@href} class={[
93 "flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors",
94
:-(
if(@active,
95 do: "bg-primary text-primary-content",
96 else: "text-base-content/70 hover:text-base-content hover:bg-base-300")
97 ]}>
98
:-(
<.hero_icon name={@icon} class={[
99 "w-5 h-5 flex-shrink-0",
100
:-(
if(@active,
101 do: "text-primary-content",
102 else: "text-base-content/60")
103 ]} />
104
:-(
<%= render_slot(@inner_block) %>
105 </a>
106 """
107 end
108
109 defp hero_icon(%{name: "home"} = assigns) do
110
:-(
~H"""
111
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
112 <path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
113 </svg>
114 """
115 end
116
117 defp hero_icon(%{name: "building-office"} = assigns) do
118
:-(
~H"""
119
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
120 <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 21h16.5M4.5 3h15l-.75 18h-13.5L4.5 3ZM12.75 8.25h.008v.008h-.008V8.25Zm0 3h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008V14.25Zm-3.75-6h.008v.008H9V8.25Zm0 3h.008v.008H9v-.008Zm0 3h.008v.008H9V14.25Zm7.5-6h.008v.008h-.008V8.25Zm0 3h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008V14.25Z" />
121 </svg>
122 """
123 end
124
125 defp hero_icon(%{name: "users"} = assigns) do
126
:-(
~H"""
127
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
128 <path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />
129 </svg>
130 """
131 end
132
133 defp hero_icon(%{name: "credit-card"} = assigns) do
134
:-(
~H"""
135
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
136 <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Z" />
137 </svg>
138 """
139 end
140
141 defp hero_icon(%{name: "chart-bar"} = assigns) do
142
:-(
~H"""
143
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
144 <path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />
145 </svg>
146 """
147 end
148
149 defp hero_icon(%{name: "cog-6-tooth"} = assigns) do
150
:-(
~H"""
151
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
152 <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a6.759 6.759 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
153 <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
154 </svg>
155 """
156 end
157
158 defp hero_icon(%{name: "document-check"} = assigns) do
159
:-(
~H"""
160
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
161 <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
162 </svg>
163 """
164 end
165
166 # Add more icons as needed
167 defp hero_icon(assigns) do
168
:-(
~H"""
169
:-(
<svg class={@class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
170 <path stroke-linecap="round" stroke-linejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3-12h.75M15 6h.75M18 6h.75" />
171 </svg>
172 """
173 end
174
175 # JavaScript helpers
176 defp hide_mobile_sidebar do
177 %JS{}
178 |> JS.hide(to: "#mobile-sidebar")
179 end
180 end
Line Hits Source