From a13f70ea1aabb5797ecc88b6a0498b6c617dec4d Mon Sep 17 00:00:00 2001 From: Andrew Tomaka <atomaka@atomaka.com> Date: Mon, 16 Jun 2025 22:35:36 -0400 Subject: [PATCH] Add user information drop down to top right (#64) Reviewed-on: https://git.atomaka.com/atomaka/budget/pulls/64 --- app/views/layouts/application.html.erb | 75 ++++++++++++++++++------ app/views/shared/_user_dropdown.html.erb | 39 ++++++++++++ test/system/credit_card_bills_test.rb | 2 +- test/system/expenses_test.rb | 2 +- test/system/sessions_test.rb | 2 + 5 files changed, 100 insertions(+), 20 deletions(-) create mode 100644 app/views/shared/_user_dropdown.html.erb diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 8441760..59e23e6 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,24 +12,63 @@ </head> <body> - <nav class="w-100 py-4 px-6 bg-gray-900 flex items-center justify-between flex-wrap"> - <div class="flex items-center"> - <%= link_to root_path, class: "mr-8" do %> - <%= image_tag "logo.svg", alt: "Family Funds Logo", class: "h-8" %> - <% end %> - <ul class="flex"> - <% if Current.user.registered? %> - <li class="mr-6"><%= link_to "Dashboard", root_path, class: "text-white" %></li> - <li class="mr-6"><%= link_to "Expenses", expenses_path, class: "text-white" %></li> - <li class="mr-6"><%= link_to "Credit Card Bills", credit_card_bills_path, class: "text-white" %></li> - <li class="mr-6"><%= link_to "Incomes", incomes_path, class: "text-white" %></li> - <li class="mr-6"><%= link_to "Members", members_path, class: "text-white" %></li> - <li class="mr-6"><%= link_to "Log out", session_path, data: {turbo_method: :delete}, class: "text-white" %></li> - <% else %> - <li class="mr-6"><%= link_to "Sign up", new_user_path, class: "text-white" %></li> - <li class="mr-6"><%= link_to "Log in", new_session_path, class: "text-white" %></li> - <% end %> - </ul> + <nav class="w-full py-4 px-4 md:px-6 bg-gray-900"> + <input type="checkbox" id="mobile-menu" class="peer hidden" /> + <div class="flex items-center justify-between"> + <div class="flex items-center flex-shrink-0"> + <%= link_to root_path, class: "mr-4 md:mr-8" do %> + <%= image_tag "logo.svg", alt: "Family Funds Logo", class: "h-8" %> + <% end %> + </div> + + <!-- Desktop menu --> + <div class="hidden lg:flex items-center flex-grow justify-center"> + <ul class="flex space-x-6"> + <% if Current.user.registered? %> + <li><%= link_to "Dashboard", root_path, class: "text-white hover:text-gray-300" %></li> + <li><%= link_to "Expenses", expenses_path, class: "text-white hover:text-gray-300" %></li> + <li><%= link_to "Credit Card Bills", credit_card_bills_path, class: "text-white hover:text-gray-300" %></li> + <li><%= link_to "Incomes", incomes_path, class: "text-white hover:text-gray-300" %></li> + <li><%= link_to "Members", members_path, class: "text-white hover:text-gray-300" %></li> + <% else %> + <li><%= link_to "Sign up", new_user_path, class: "text-white hover:text-gray-300" %></li> + <li><%= link_to "Log in", new_session_path, class: "text-white hover:text-gray-300" %></li> + <% end %> + </ul> + </div> + + <div class="flex items-center space-x-4 flex-shrink-0"> + <!-- Hamburger menu button --> + <label for="mobile-menu" + class="lg:hidden text-white hover:text-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-300 rounded-lg p-2 cursor-pointer" + > + <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path> + </svg> + </label> + + <% if Current.user.registered? %> + <%= render 'shared/user_dropdown' %> + <% end %> + </div> + </div> + + <!-- Mobile menu --> + <div class="lg:hidden mt-4 hidden peer-checked:block"> + <div class="border-t border-gray-700 pt-4"> + <ul class="space-y-2"> + <% if Current.user.registered? %> + <li><%= link_to "Dashboard", root_path, class: "block text-white hover:text-gray-300 hover:bg-gray-800 px-3 py-2 rounded-md text-base font-medium" %></li> + <li><%= link_to "Expenses", expenses_path, class: "block text-white hover:text-gray-300 hover:bg-gray-800 px-3 py-2 rounded-md text-base font-medium" %></li> + <li><%= link_to "Credit Card Bills", credit_card_bills_path, class: "block text-white hover:text-gray-300 hover:bg-gray-800 px-3 py-2 rounded-md text-base font-medium" %></li> + <li><%= link_to "Incomes", incomes_path, class: "block text-white hover:text-gray-300 hover:bg-gray-800 px-3 py-2 rounded-md text-base font-medium" %></li> + <li><%= link_to "Members", members_path, class: "block text-white hover:text-gray-300 hover:bg-gray-800 px-3 py-2 rounded-md text-base font-medium" %></li> + <% else %> + <li><%= link_to "Sign up", new_user_path, class: "block text-white hover:text-gray-300 hover:bg-gray-800 px-3 py-2 rounded-md text-base font-medium" %></li> + <li><%= link_to "Log in", new_session_path, class: "block text-white hover:text-gray-300 hover:bg-gray-800 px-3 py-2 rounded-md text-base font-medium" %></li> + <% end %> + </ul> + </div> </div> </nav> diff --git a/app/views/shared/_user_dropdown.html.erb b/app/views/shared/_user_dropdown.html.erb new file mode 100644 index 0000000..590d008 --- /dev/null +++ b/app/views/shared/_user_dropdown.html.erb @@ -0,0 +1,39 @@ +<div class="relative group"> + <input type="checkbox" id="user-dropdown" class="peer hidden" /> + <label for="user-dropdown" + class="flex items-center space-x-2 text-white hover:text-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-300 rounded-lg p-2 cursor-pointer" + > + <div class="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center text-white font-semibold text-sm flex-shrink-0"> + <%= Current.user.email.first.upcase %> + </div> + <span class="hidden xl:block font-medium truncate max-w-48"><%= Current.user.email %></span> + <svg class="w-4 h-4 transform transition-transform duration-200 flex-shrink-0 peer-checked:rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24"> + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> + </svg> + </label> + + <!-- Invisible overlay to close dropdown when clicking outside --> + <label for="user-dropdown" class="fixed inset-0 z-40 hidden peer-checked:block cursor-default"></label> + + <div + class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 z-50 hidden peer-checked:block" + > + <div class="py-1"> + <%= link_to user_path(Current.user), class: "flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" do %> + <svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"> + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path> + </svg> + Profile + <% end %> + <hr class="my-1 border-gray-200"> + <%= link_to session_path, + data: {turbo_method: :delete}, + class: "flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" do %> + <svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"> + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path> + </svg> + Log out + <% end %> + </div> + </div> +</div> \ No newline at end of file diff --git a/test/system/credit_card_bills_test.rb b/test/system/credit_card_bills_test.rb index 5c829c8..ec2fb7e 100644 --- a/test/system/credit_card_bills_test.rb +++ b/test/system/credit_card_bills_test.rb @@ -37,7 +37,7 @@ class CreditCardBillsTest < ApplicationSystemTestCase test "should destroy Credit card bill" do visit credit_card_bill_url(@credit_card_bill) - click_on "Delete credit card bill", match: :first + accept_prompt { click_on "Delete credit card bill", match: :first } assert_text "Credit card bill was successfully destroyed" end diff --git a/test/system/expenses_test.rb b/test/system/expenses_test.rb index d23f851..ba276bf 100644 --- a/test/system/expenses_test.rb +++ b/test/system/expenses_test.rb @@ -47,7 +47,7 @@ class ExpensesTest < ApplicationSystemTestCase test "should destroy Expense" do visit expense_url(@expense) - click_on "Delete expense", match: :first + accept_prompt { click_on "Delete expense", match: :first } assert_text "Expense was successfully destroyed" end diff --git a/test/system/sessions_test.rb b/test/system/sessions_test.rb index 958d1a5..e1d531b 100644 --- a/test/system/sessions_test.rb +++ b/test/system/sessions_test.rb @@ -15,6 +15,8 @@ class SessionsTest < ApplicationSystemTestCase login(@user.email) visit root_url + # Open the user dropdown by clicking the checkbox label + find('label[for="user-dropdown"]').click click_on "Log out", match: :first assert_text "Session was successfully destroyed"