Add user menu
This commit is contained in:
@@ -320,25 +320,26 @@
|
||||
@apply hidden absolute;
|
||||
}
|
||||
|
||||
.btn {
|
||||
@utility btn {
|
||||
@apply px-3 py-2 rounded-lg text-sm font-medium cursor-pointer disabled:cursor-not-allowed focus:outline-gray-500;
|
||||
}
|
||||
|
||||
.btn--primary {
|
||||
@utility btn--primary {
|
||||
@apply bg-gray-900 text-white hover:bg-gray-700 disabled:bg-gray-50 disabled:hover:bg-gray-50 disabled:text-gray-400;
|
||||
}
|
||||
|
||||
.btn--secondary {
|
||||
@utility btn--secondary {
|
||||
@apply bg-gray-50 hover:bg-gray-100 text-gray-900;
|
||||
}
|
||||
|
||||
.btn--outline {
|
||||
@utility btn--outline {
|
||||
@apply border border-alpha-black-200 text-gray-900 hover:bg-gray-50 disabled:bg-gray-50 disabled:hover:bg-gray-50 disabled:text-gray-400;
|
||||
}
|
||||
|
||||
.btn--ghost {
|
||||
@utility btn--ghost {
|
||||
@apply border border-transparent text-gray-900 hover:bg-gray-50;
|
||||
}
|
||||
|
||||
.scrollbar {
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Controller } from "@hotwired/stimulus";
|
||||
|
||||
// Connects to data-controller="tabs"
|
||||
export default class extends Controller {
|
||||
static classes = ["active"];
|
||||
static classes = ["active", "inactive"];
|
||||
static targets = ["btn", "tab"];
|
||||
static values = { defaultTab: String };
|
||||
|
||||
@@ -27,14 +27,18 @@ export default class extends Controller {
|
||||
};
|
||||
|
||||
updateClasses = (selectedId) => {
|
||||
this.btnTargets.forEach((btn) =>
|
||||
btn.classList.remove(...this.activeClasses),
|
||||
);
|
||||
this.btnTargets.forEach((btn) => {
|
||||
btn.classList.remove(...this.activeClasses);
|
||||
btn.classList.remove(...this.inactiveClasses);
|
||||
});
|
||||
|
||||
this.tabTargets.forEach((tab) => tab.classList.add("hidden"));
|
||||
|
||||
this.btnTargets.forEach((btn) => {
|
||||
if (btn.dataset.id === selectedId) {
|
||||
btn.classList.add(...this.activeClasses);
|
||||
} else {
|
||||
btn.classList.add(...this.inactiveClasses);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -4,11 +4,20 @@
|
||||
class="space-y-3"
|
||||
data-controller="tabs"
|
||||
data-tabs-active-class="bg-white shadow-sm text-gray-900"
|
||||
data-tabs-inactive-class="text-gray-500"
|
||||
data-tabs-default-tab-value="assets-tab">
|
||||
<div class="bg-gray-100 rounded-lg p-1 flex">
|
||||
<button type="button" data-id="assets-tab" class="w-1/3 px-2 py-1 rounded-md text-gray-500 text-sm bg-white shadow-sm text-gray-900" data-tabs-target="btn" data-action="click->tabs#select">Assets</button>
|
||||
<button type="button" data-id="debts-tab" class="w-1/3 px-2 py-1 rounded-md text-gray-500 text-sm" data-tabs-target="btn" data-action="click->tabs#select">Debts</button>
|
||||
<button type="button" data-id="all-tab" class="w-1/3 px-2 py-1 rounded-md text-gray-500 text-sm" data-tabs-target="btn" data-action="click->tabs#select">All</button>
|
||||
<button type="button" data-id="assets-tab" class="w-1/3 px-2 py-1 rounded-md text-sm bg-white shadow-sm text-gray-900" data-tabs-target="btn" data-action="click->tabs#select">
|
||||
Assets
|
||||
</button>
|
||||
|
||||
<button type="button" data-id="debts-tab" class="w-1/3 px-2 py-1 rounded-md text-gray-500 text-sm" data-tabs-target="btn" data-action="click->tabs#select">
|
||||
Debts
|
||||
</button>
|
||||
|
||||
<button type="button" data-id="all-tab" class="w-1/3 px-2 py-1 rounded-md text-gray-500 text-sm" data-tabs-target="btn" data-action="click->tabs#select">
|
||||
All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div data-tabs-target="tab" id="assets-tab">
|
||||
@@ -1,131 +0,0 @@
|
||||
<div class="flex items-center justify-between">
|
||||
<%= link_to root_path do %>
|
||||
<%= image_tag "logo.svg", alt: "Maybe", class: "h-[22px]" %>
|
||||
<% end %>
|
||||
<div id="user-menu" data-controller="menu">
|
||||
<button data-menu-target="button">
|
||||
<div class="w-9 h-9">
|
||||
<%= render "settings/user_avatar", user: Current.user, variant: :small %>
|
||||
</div>
|
||||
</button>
|
||||
<div data-menu-target="content" class="hidden absolute w-[240px] z-10 left-[255px] top-[72px] divide-y divide-alpha-black-100 bg-white rounded-sm shadow-xs border border-alpha-black-25">
|
||||
<div class="p-3 flex items-center gap-3">
|
||||
<div class="w-9 h-9 shrink-0">
|
||||
<%= render "settings/user_avatar", user: Current.user, variant: :small, lazy: true %>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden text-ellipsis">
|
||||
<span class="text-gray-900 font-medium text-sm"><%= Current.user.display_name %></span>
|
||||
<% if Current.user.display_name != Current.user.email %>
|
||||
<span class="text-gray-500 text-sm"><%= Current.user.email %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if self_hosted? %>
|
||||
<div class="p-3">
|
||||
<p class="text-sm">
|
||||
<span class="font-medium text-gray-900">Version:</span>
|
||||
<%= link_to Maybe.version.to_release_tag, "https://github.com/maybe-finance/maybe/releases/tag/#{Maybe.version.to_release_tag}", target: "_blank", class: "hover:underline" %>
|
||||
(<%= link_to Maybe.commit_sha.first(7), "https://github.com/maybe-finance/maybe/commit/#{Maybe.commit_sha}", target: "_blank", class: "hover:underline" %>)
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="p-1">
|
||||
<%= link_to settings_profile_path(return_to: request.fullpath), class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("settings", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Settings</span>
|
||||
<% end %>
|
||||
<div class="flex justify-between items-center gap-2">
|
||||
<div class="flex items-center gap-2 rounded-lg px-3 py-2">
|
||||
<%= lucide_icon("app-window", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<div>
|
||||
<span class="text-gray-900 text-sm">Demo mode</span>
|
||||
<span class="text-gray-500 text-xs block">Coming soon...</span>
|
||||
</div>
|
||||
</div>
|
||||
<%# TODO: This will be a form toggle when implemented %>
|
||||
<div class="relative inline-block cursor-not-allowed" title="Coming soon...">
|
||||
<label class="cursor-not-allowed block bg-gray-100 w-9 h-5 rounded-full after:content-[''] after:block after:absolute after:top-0.5 after:left-0.5 after:bg-white after:w-4 after:h-4 after:rounded-full after:transition-transform after:duration-300 after:ease-in-out peer-checked:bg-green-600 peer-checked:after:translate-x-4"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-1">
|
||||
<%= link_to changelog_path, class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("box", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Changelog</span>
|
||||
<% end %>
|
||||
<%= link_to feedback_path, class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("megaphone", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Feedback</span>
|
||||
<% end %>
|
||||
<% if self_hosted? %>
|
||||
<%= link_to "https://link.maybe.co/discord", class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("message-square-more", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Contact</span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= link_to "mailto:hello@maybefinance.com", class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2", onclick: "Intercom('showNewMessage'); return false;" do %>
|
||||
<%= lucide_icon("message-square-more", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Contact</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="p-1">
|
||||
<%= button_to session_path(Current.session), method: :delete, class: "w-full text-red-400 flex gap-1 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("log-out", class: "w-5 h-5 shrink-0") %>
|
||||
<span class="text-sm">Logout</span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="mt-6 space-y-1">
|
||||
<li>
|
||||
<%= sidebar_link_to t(".dashboard"), root_path, icon: "layout-grid" %>
|
||||
</li>
|
||||
<li>
|
||||
<%= sidebar_link_to t(".accounts"), summary_accounts_path, icon: "layers" %>
|
||||
</li>
|
||||
<li>
|
||||
<%= sidebar_link_to t(".transactions"), transactions_path, icon: "credit-card" %>
|
||||
</li>
|
||||
<li>
|
||||
<%= sidebar_link_to t(".budgeting"), budgets_path, icon: "map" %>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="flex flex-col mt-6">
|
||||
<div class="flex items-center justify-between px-3 py-2 mb-2">
|
||||
<div class="flex items-center gap-2 text-xs uppercase text-gray-500">
|
||||
<%= link_to accounts_path, class: "text-xs uppercase text-gray-500 font-bold tracking-wide" do %>
|
||||
<%= t(".portfolio") %>
|
||||
<% end %>
|
||||
<span class="font-bold tracking-wide">•</span>
|
||||
|
||||
<%= form_with url: list_accounts_path, method: :get, data: { controller: Current.family.accounts.any? ? "auto-submit-form" : nil, turbo_frame: "account-list" } do |form| %>
|
||||
<%= period_select form: form, selected: "last_30_days", classes: "w-full border-none pl-2 pr-7 text-xs bg-transparent gap-1 cursor-pointer font-semibold tracking-wide focus:outline-hidden focus:ring-0" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= link_to new_account_path, id: "sidebar-new-account", class: "block hover:bg-gray-100 font-semibold text-gray-900 flex items-center rounded p-1", title: t(".new_account"), data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= turbo_frame_tag "account-list", target: "_top" do %>
|
||||
<% if Current.family.accounts.any? %>
|
||||
<% account_groups.each do |group| %>
|
||||
<%= render "accounts/account_list", group: group %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= link_to new_account_path, class: "flex items-center min-h-10 gap-4 px-3 py-2 mb-1 text-gray-500 text-sm font-medium rounded-[10px] hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<%= tag.p t(".new_account") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -7,7 +7,7 @@
|
||||
<%= render "layouts/shared/fixed_content" %>
|
||||
|
||||
<div class="flex h-full bg-gray-25">
|
||||
<nav class="shrink-0 w-[84px] py-4 mr-3">
|
||||
<nav class="flex flex-col shrink-0 w-[84px] py-4 mr-3">
|
||||
<div class="pl-2 mb-3">
|
||||
<%= image_tag "logomark-color.svg", class: "w-9 h-9 mx-auto" %>
|
||||
</div>
|
||||
@@ -17,13 +17,17 @@
|
||||
<%= render "layouts/sidebar/nav_item", name: "Transactions", path: transactions_path, icon_key: "credit-card", active: page_active?(transactions_path) %>
|
||||
<%= render "layouts/sidebar/nav_item", name: "Budgets", path: budgets_path, icon_key: "layout-grid", active: page_active?(budgets_path) %>
|
||||
</div>
|
||||
|
||||
<div class="pl-2 mt-auto mx-auto">
|
||||
<%= render "users/user_menu", user: Current.user %>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="py-4 w-[260px] shrink-0 h-full overflow-y-auto">
|
||||
<% if content_for?(:sidebar) %>
|
||||
<%= yield :sidebar %>
|
||||
<% else %>
|
||||
<%= render "layouts/default_sidebar", accounts: Current.family.accounts.active.to_a %>
|
||||
<%= render "accounts/account_sidebar_tabs", accounts: Current.family.accounts.active.to_a %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<%= csrf_meta_tags %>
|
||||
<%= csp_meta_tag %>
|
||||
|
||||
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
|
||||
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
||||
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
||||
|
||||
<%= javascript_include_tag "https://cdn.plaid.com/link/v2/stable/link-initialize.js" %>
|
||||
|
||||
69
app/views/users/_user_menu.html.erb
Normal file
69
app/views/users/_user_menu.html.erb
Normal file
@@ -0,0 +1,69 @@
|
||||
<%# locals: (user:) %>
|
||||
|
||||
<div id="user-menu" data-controller="menu">
|
||||
<button data-menu-target="button">
|
||||
<div class="w-9 h-9 cursor-pointer">
|
||||
<%= render "settings/user_avatar", user: user, variant: :small %>
|
||||
</div>
|
||||
</button>
|
||||
<div data-menu-target="content" class="hidden absolute w-[240px] z-10 left-[255px] top-[72px] divide-y divide-alpha-black-100 bg-white rounded-sm shadow-xs border border-alpha-black-25">
|
||||
<div class="p-3 flex items-center gap-3">
|
||||
<div class="w-9 h-9 shrink-0">
|
||||
<%= render "settings/user_avatar", user: user, variant: :small, lazy: true %>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden text-ellipsis">
|
||||
<span class="text-gray-900 font-medium text-sm"><%= user.display_name %></span>
|
||||
<% if user.display_name != user.email %>
|
||||
<span class="text-gray-500 text-sm"><%= user.email %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if self_hosted? %>
|
||||
<div class="p-3">
|
||||
<p class="text-sm">
|
||||
<span class="font-medium text-gray-900">Version:</span>
|
||||
<%= link_to Maybe.version.to_release_tag, "https://github.com/maybe-finance/maybe/releases/tag/#{Maybe.version.to_release_tag}", target: "_blank", class: "hover:underline" %>
|
||||
(<%= link_to Maybe.commit_sha.first(7), "https://github.com/maybe-finance/maybe/commit/#{Maybe.commit_sha}", target: "_blank", class: "hover:underline" %>)
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="p-1">
|
||||
<%= link_to settings_profile_path(return_to: request.fullpath), class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("settings", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Settings</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="p-1">
|
||||
<%= link_to changelog_path, class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("box", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Changelog</span>
|
||||
<% end %>
|
||||
<%= link_to feedback_path, class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("megaphone", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Feedback</span>
|
||||
<% end %>
|
||||
<% if self_hosted? %>
|
||||
<%= link_to "https://link.maybe.co/discord", class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("message-square-more", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Contact</span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= link_to "mailto:hello@maybefinance.com", class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2", onclick: "Intercom('showNewMessage'); return false;" do %>
|
||||
<%= lucide_icon("message-square-more", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Contact</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="p-1">
|
||||
<%= button_to session_path(Current.session), method: :delete, class: "w-full text-red-400 flex gap-1 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||
<%= lucide_icon("log-out", class: "w-5 h-5 shrink-0") %>
|
||||
<span class="text-sm">Logout</span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user