mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-10 07:55:21 +02:00
Pre-launch design sync with Figma spec (#2154)
* Add lookbook + viewcomponent, organize design system file * Build menu component * Button updates * More button fixes * Replace all menus with new ViewComponent * Checkpoint: fix tests, all buttons and menus converted * Split into Link and Button components for clarity * Button cleanup * Simplify custom confirmation configuration in views * Finalize button, link component API * Add toggle field to custom form builder + Component * Basic tabs component * Custom tabs, convert all menu / tab instances in app * Gem updates * Centralized icon helper * Update all icon usage to central helper * Lint fixes * Centralize all disclosure instances * Dialog replacements * Consolidation of all dialog styles * Test fixes * Fix app layout issues, move to component with slots * Layout simplification * Flakey test fix * Fix dashboard mobile issues * Finalize homepage * Lint fixes * Fix shadows and borders in dark mode * Fix tests * Remove stale class * Fix filled icon logic * Move transparent? to public interface
This commit is contained in:
parent
1aafed5f8b
commit
90a9546f32
291 changed files with 4143 additions and 3104 deletions
|
@ -1,33 +1,26 @@
|
|||
<div class="flex flex-col items-center justify-start h-full p-6 text-center">
|
||||
<div class="border border-secondary rounded-lg p-4 bg-container">
|
||||
<div class="w-16 h-16 bg-surface-inset rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<%= icon("sparkles") %>
|
||||
</div>
|
||||
|
||||
<h3 class="text-lg font-medium text-primary mb-2">Enable Personal Finance AI</h3>
|
||||
|
||||
<p class="text-gray-600 mb-6 text-sm">
|
||||
<% if Current.user.ai_available? %>
|
||||
Our personal finance AI can help answer questions about your finances and provide insights based on your data.
|
||||
To use this feature, you'll need to explicitly enable it.
|
||||
<% else %>
|
||||
To use the AI assistant, you need to set the <code class="bg-surface-inset px-1 py-0.5 rounded font-mono text-xs">OPENAI_ACCESS_TOKEN</code>
|
||||
environment variable in your self-hosted instance.
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
<% unless self_hosted? %>
|
||||
<p class="text-gray-600 mb-6 text-sm">
|
||||
NOTE: During beta testing, we'll be monitoring usage and AI conversations to improve the assistant.
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if Current.user.ai_available? %>
|
||||
<%= form_with url: user_path(Current.user), method: :patch, class: "w-full", data: { turbo: false } do |form| %>
|
||||
<%= form.hidden_field "user[ai_enabled]", value: true %>
|
||||
<%= form.hidden_field "user[redirect_to]", value: "home" %>
|
||||
<%= form.submit "Enable AI Assistant", class: "cursor-pointer hover:bg-black w-full py-2 px-4 bg-gray-800 text-white rounded-lg text-sm font-medium" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<div class="rounded-lg p-4 bg-container shadow-border-xs">
|
||||
<div class="flex justify-center">
|
||||
<%= render "chats/ai_avatar" %>
|
||||
</div>
|
||||
|
||||
<h3 class="text-sm font-medium text-primary mb-1 -mt-2 text-center">Enable Maybe AI</h3>
|
||||
|
||||
<p class="text-gray-600 mb-4 text-sm text-center">
|
||||
<% if Current.user.ai_available? %>
|
||||
Maybe AI can answer financial questions and provide insights based on your data. To use this feature you'll need to explicitly enable it.
|
||||
<% else %>
|
||||
To use the AI assistant, you need to set the <code class="bg-surface-inset px-1 py-0.5 rounded font-mono text-xs">OPENAI_ACCESS_TOKEN</code>
|
||||
environment variable in your self-hosted instance.
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
<% if Current.user.ai_available? %>
|
||||
<%= form_with url: user_path(Current.user), method: :patch, class: "w-full", data: { turbo: false } do |form| %>
|
||||
<%= form.hidden_field "user[ai_enabled]", value: true %>
|
||||
<%= form.hidden_field "user[redirect_to]", value: "home" %>
|
||||
<%= form.submit "Enable Maybe AI", class: "cursor-pointer hover:bg-black w-full py-2 px-4 bg-gray-800 text-white rounded-lg text-sm font-medium" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<p class="text-xs text-secondary text-center mt-2">Disable anytime. All data sent to our LLM providers is anonymized.</p>
|
||||
</div>
|
||||
|
|
|
@ -9,8 +9,14 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<%= contextual_menu icon: "more-vertical" do %>
|
||||
<%= contextual_menu_item("Edit chat", url: edit_chat_path(chat), icon: "pencil", turbo_frame: dom_id(chat, :title)) %>
|
||||
<%= contextual_menu_destructive_item("Delete chat", chat_path(chat)) %>
|
||||
<%= render MenuComponent.new(icon_vertical: true) do |menu| %>
|
||||
<% menu.with_item(variant: "link", text: "Edit chat", href: edit_chat_path(chat), icon: "pencil", frame: dom_id(chat, "title")) %>
|
||||
<% menu.with_item(
|
||||
variant: "button",
|
||||
text: "Delete chat",
|
||||
href: chat_path(chat),
|
||||
icon: "trash-2",
|
||||
method: :delete,
|
||||
confirm: CustomConfirm.for_resource_deletion("Chat")) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -13,12 +13,23 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<%= contextual_menu icon: "more-vertical", id: "chat-menu" do %>
|
||||
<%= contextual_menu_item "Start new chat", url: new_chat_path, icon: "plus" %>
|
||||
<%= render MenuComponent.new(icon_vertical: true) do |menu| %>
|
||||
<% menu.with_item(variant: "link", text: "Start new chat", href: new_chat_path, icon: "plus") %>
|
||||
|
||||
<% unless chat.new_record? %>
|
||||
<%= contextual_menu_item "Edit chat title", url: edit_chat_path(chat, ctx: "chat"), icon: "pencil", turbo_frame: dom_id(chat, "title") %>
|
||||
<%= contextual_menu_destructive_item "Delete chat", chat_path(chat), turbo_confirm: "Are you sure you want to delete this chat?" %>
|
||||
<% menu.with_item(
|
||||
variant: "link",
|
||||
text: "Edit chat title",
|
||||
href: edit_chat_path(chat, ctx: "chat"),
|
||||
icon: "pencil", data: { turbo_frame: dom_id(chat, "title") }) %>
|
||||
|
||||
<% menu.with_item(
|
||||
variant: "button",
|
||||
text: "Delete chat",
|
||||
href: chat_path(chat),
|
||||
icon: "trash-2",
|
||||
method: :delete,
|
||||
confirm: CustomConfirm.for_resource_deletion("Chat")) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</nav>
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
<div class="flex items-center justify-between gap-2">
|
||||
<p class="text-xs text-red-500">Failed to generate response. Please try again.</p>
|
||||
|
||||
<%= button_to retry_chat_path(chat), method: :post, class: "btn btn--primary" do %>
|
||||
<span>Retry</span>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "Retry",
|
||||
href: retry_chat_path(chat),
|
||||
) %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
<%= turbo_frame_tag chat_frame do %>
|
||||
<div class="flex flex-col h-full md:p-4">
|
||||
<nav class="mb-6">
|
||||
<% back_path = @last_viewed_chat ? chat_path(@last_viewed_chat) : new_chat_path %>
|
||||
<%= link_to back_path, class: "w-9 h-9 flex items-center justify-center rounded-lg hover:bg-surface-hover" do %>
|
||||
<%= icon("arrow-left", color: "gray" ) %>
|
||||
<% end %>
|
||||
</nav>
|
||||
|
||||
<div class="grow flex flex-col">
|
||||
<h1 class="text-xl font-medium mb-6">Chats</h1>
|
||||
|
||||
<div data-controller="chat hotkey">
|
||||
<%= turbo_frame_tag chat_frame do %>
|
||||
<div class="flex flex-col h-full md:p-4">
|
||||
<% if @chats.any? %>
|
||||
<div class="space-y-2 px-0.5">
|
||||
<%= render @chats %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-center py-12 bg-container rounded-lg border border-primary">
|
||||
<div class="w-16 h-16 bg-surface-inset rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<%= icon("message-square", size: "lg") %>
|
||||
</div>
|
||||
<h3 class="text-lg font-medium text-primary mb-1">No chats yet</h3>
|
||||
<p class="text-gray-500 mb-4">Start a new conversation with the AI assistant</p>
|
||||
</div>
|
||||
<div class="mt-auto p-4 lg:mt-auto">
|
||||
<%= render "messages/chat_form", chat: nil %>
|
||||
</div>
|
||||
<nav class="mb-6">
|
||||
<% back_path = @last_viewed_chat ? chat_path(@last_viewed_chat) : new_chat_path %>
|
||||
<%= link_to back_path, class: "w-9 h-9 flex items-center justify-center rounded-lg hover:bg-surface-hover" do %>
|
||||
<%= icon("arrow-left", color: "gray" ) %>
|
||||
<% end %>
|
||||
</nav>
|
||||
<% end %>
|
||||
|
||||
<div class="grow flex flex-col">
|
||||
<% if @chats.any? %>
|
||||
<h1 class="text-xl font-medium mb-6">Chats</h1>
|
||||
<div class="space-y-2 px-0.5">
|
||||
<%= render @chats %>
|
||||
</div>
|
||||
<% else %>
|
||||
<h1 class="sr-only">Chats</h1>
|
||||
<div class="mt-auto py-8">
|
||||
<%= render "chats/ai_greeting" %>
|
||||
</div>
|
||||
|
||||
<%= render "messages/chat_form" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -1,35 +1,38 @@
|
|||
<%= turbo_frame_tag chat_frame do %>
|
||||
<%= turbo_stream_from @chat %>
|
||||
<div data-controller="chat hotkey">
|
||||
<%= turbo_frame_tag chat_frame do %>
|
||||
<%= turbo_stream_from @chat %>
|
||||
|
||||
<h1 class="sr-only"><%= @chat.title %></h1>
|
||||
<h1 class="sr-only"><%= @chat.title %></h1>
|
||||
|
||||
<div class="flex flex-col h-full">
|
||||
<div class="md:p-4">
|
||||
<%= render "chats/chat_nav", chat: @chat %>
|
||||
</div>
|
||||
<div class="flex flex-col h-full">
|
||||
<div class="md:p-4">
|
||||
<%= render "chats/chat_nav", chat: @chat %>
|
||||
</div>
|
||||
|
||||
<div id="messages" class="grow overflow-y-auto p-4 space-y-6" data-chat-target="messages">
|
||||
<% if @chat.conversation_messages.any? %>
|
||||
<% @chat.conversation_messages.ordered.each do |message| %>
|
||||
<%= render message %>
|
||||
<div id="messages" class="grow overflow-y-auto p-4 space-y-6 pb-24 lg:pb-4" data-chat-target="messages">
|
||||
<% if @chat.conversation_messages.any? %>
|
||||
<% @chat.conversation_messages.ordered.each do |message| %>
|
||||
<%= render message %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="mt-auto">
|
||||
<%= render "chats/ai_greeting", context: "chat" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="mt-auto">
|
||||
<%= render "chats/ai_greeting", context: "chat" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if params[:thinking].present? %>
|
||||
<%= render "chats/thinking_indicator", chat: @chat %>
|
||||
<% end %>
|
||||
<% if params[:thinking].present? %>
|
||||
<%= render "chats/thinking_indicator", chat: @chat %>
|
||||
<% end %>
|
||||
|
||||
<% if @chat.error.present? && @chat.needs_assistant_response? %>
|
||||
<%= render "chats/error", chat: @chat %>
|
||||
<% end %>
|
||||
<% if @chat.error.present? && @chat.needs_assistant_response? %>
|
||||
<%= render "chats/error", chat: @chat %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%# DESKTOP - Chat form %>
|
||||
<div class="p-4 lg:mt-auto fixed lg:static left-0 bottom-16 w-full bg-surface">
|
||||
<%= render "messages/chat_form", chat: @chat %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 lg:mt-auto">
|
||||
<%= render "messages/chat_form", chat: @chat %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue