I have a tab where the first tab renders the devise controller (edit.html.erb view) and the second one I want to render the ChartsController. How can I do this in Rails 7? My code:
edit.html.erb:
<div class="bg-white p-8">
<div class="tab-section rounded-lg min-h-[400px]">
<div class="flex flex-wrap gap-1 border-b border-stone-300">
<button class="inline-block p-4 text-stone-600 font-semibold rounded-t-lg active"
data-tab-target="#tab1">Editar Perfil</button>
<button class="inline-block p-4 text-stone-600 font-semibold rounded-t-lg active"
data-tab-target="#tab2">Estatística </button>
</div>
<div class="mt-4">
<div id="tab1" class="tab-content text-gray-700">
<div class="flex">
<aside class="card bg-white border border-gray-300 rounded-lg text-center justify-center flex flex-col items-center w-1/3">
<% if resource.avatar? %>
<img src="<%= resource.avatar %>" alt="Avatar" class="rounded-full border-yellow-500 border-4 border-secondary w-72 h-72 mb-4" />
<% else %>
<%= lucide_icon('user-round', class: "rounded-full border-yellow-500 border-4 border-secondary w-72 h-72 mb-4") %>
<% end %>
<h2 class="text-2xl font-semibold mb-4"><%= resource.name %></h2>
<p class="text-lg">
Quantidade de horas que trabalha na semana: <br />
<strong class="text-4xl"><%= resource.formatted_hours_per_week %></strong>
</p>
<br />
<p class="text-lg">
Tempo restante do compromisso: <br />
<strong class="text-4xl"><%= resource.commitments.last.time_remaining if resource.commitments.any? %></strong>
</p>
</aside>
<main class="flex-1 p-4">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'space-y-4' }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :name, "Nome", class: 'block font-semibold' %>
<%= f.text_field :name, class: 'mt-1 block w-full border border-gray-300 rounded-md p-2', placeholder: "Seu nome" %>
</div>
<div class="field">
<%= f.label :email, class: 'block font-semibold' %>
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: 'mt-1 block w-full border border-gray-300 rounded-md p-2', placeholder: "Seu email" %>
</div>
<div class="field">
<%= f.label :avatar, class: 'block font-semibold' %>
<%= f.url_field :avatar, class: 'mt-1 block w-full border border-gray-300 rounded-md p-2', placeholder: "URL da imagem (ex: https://github.com/eltonsantos.png)" %>
</div>
<div class="field">
<%= f.label :hours_per_week, "Horas por semana", class: 'block font-semibold' %>
<%= f.number_field :hours_per_week, step: 0.25, class: 'mt-1 block w-full border border-gray-300 rounded-md p-2', placeholder: "Quantidade de horas trabalhadas por semana" %>
</div>
<div class="field">
<%= f.label :password, "Senha", class: 'block font-semibold' %>
<%= f.password_field :password, autocomplete: "new-password", class: 'mt-1 block w-full border border-gray-300 rounded-md p-2', placeholder: "Nova senha (deixe em branco para não alterar)" %>
</div>
<div class="field">
<%= f.label :password_confirmation, "Confirmação de senha", class: 'block font-semibold' %>
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: 'mt-1 block w-full border border-gray-300 rounded-md p-2', placeholder: "Confirme a nova senha" %>
</div>
<div class="field">
<%= f.label :current_password, "Senha atual", class: 'block font-semibold' %>
<%= f.password_field :current_password, autocomplete: "current-password", class: 'mt-1 block w-full border border-gray-300 rounded-md p-2', placeholder: "Senha atual" %>
</div>
<div class="actions mt-4">
<%= f.submit "Atualizar", class: 'bg-blue-600 text-white font-semibold py-2 px-4 rounded' %>
</div>
<% end %>
<h3 class="text-lg font-semibold mt-6 border-t-4 border-red-400">Zona de perigo</h3>
<div>
<%= button_to registration_path(resource_name), data: { confirm: "Você tem certeza? Essa ação não poderá ser desfeita e todos os dados serão perdidos!" }, method: :delete, class: 'button orange mt-3 inline-flex items-center bg-red-500 text-white px-4 py-2 rounded hover:bg-red-600 font-bold' do %>
<span class="mr-2">
<%= lucide_icon('x', class: 'text-white') %>
</span>
Cancelar minha conta
<% end %>
</div>
</main>
</div>
</div>
<div id="tab2" class="hidden tab-content text-gray-700">
<h4 class="font-bold mt-9 mb-4 text-2xl">Estatística</h4>
<%= render partial: 'charts/index', locals: { tarefa: Task.first } %>
</div>
</div>
</div>
</div>
<script>
const tabs = document.querySelectorAll('[data-tab-target]');
const activeClass = 'text-stone-900';
tabs[0].classList.add(activeClass);
document.querySelector('#tab1').classList.remove('hidden');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const targetContent = document.querySelector(tab.dataset.tabTarget);
document.querySelectorAll('.tab-content').forEach(content => content.classList.add('hidden'));
targetContent.classList.remove('hidden');
document.querySelectorAll('.text-stone-900').forEach(activeTab => activeTab.classList.remove(activeClass));
console.log(tab)
tab.classList.add(activeClass);
});
});
</script>
The first tab is DeviseController, and the second is it:
class ChartsController < ApplicationController
def index
end
end
My second view:
/app/views/charts/_index.html.erb:
<h2>Conteúdo da Segunda Aba</h2>
<p>Esta é a view renderizada pelo ChartsController.</p>
<%= tarefa.title %>
<%= tarefa.description %>
<%= tarefa.category.name %>
<%= tarefa.hours %>
I don’t know if I explained everything correctly, but it’s something simple, I just have a tab, which has 2 tabs, so when I access the page, the first selected tab renders the DeviseController#edit, when I click on the second, I need it to render the ChartsController#index, that’s all. However, I’ve tried everything, I asked the gpt chat, Claude and none of them helped me.