Skip to content
Snippets Groups Projects
Commit 218c8fcd authored by Teal's avatar Teal
Browse files

Merge branch 'update-darkmode' into 'main'

Dark Mode & UI Improvements

See merge request !28
parents 7447aa53 d82c5e9e
No related branches found
No related tags found
1 merge request!28Dark Mode & UI Improvements
Pipeline #38345 passed
Showing
with 364 additions and 94 deletions
<div class="mb-6 <%= Time.parse(date).end_of_day < now ? "past" : "future" %>">
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3"><%= date %></h3>
<h3 class="sticky top-0 z-10 text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3 bg-white dark:bg-gray-800 py-2"><%= date %></h3>
<ul class="space-y-3">
<% assignments_on_date.each do |assignment| %>
<li class="<%= assignment.session.starts_at < now ? "past" : "future" %> pl-4 border-l-4 border-gray-200 dark:border-gray-700">
......
<div class="container mx-auto px-4 py-8">
<div class="max-w-full">
<div class="flex items-center mb-6">
<h1 class="text-2xl font-bold dark:text-gray-200">
Assignments for
<%= link_to @user.name, user_assignments_path(@user), class: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" %>
</h1>
<%= link_to user_assignments_path(@user, format: 'ics'), class: "btn btn-info-light ml-4" do %>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 24" fill="currentColor" aria-hidden="true" class="size-5 inline-block mr-1"><path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd"></path></svg> iCal
<% end %>
</div>
<% now = Time.now %>
<div class="mb-8">
<h2 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-4">List View</h2>
<div class="bg-white dark:bg-gray-800 shadow rounded-lg p-6">
<% @user.assignments.includes(:session, session: :conference).order('sessions.starts_at').group_by { |a| a.session.starts_at.strftime('%Y-%m-%d') }.each do |date, assignments_on_date| %>
<%= render partial: 'listview_date', locals: { assignments_on_date:, date:, now: } %>
<div class="flex items-center mb-6">
<h1 class="text-2xl font-bold dark:text-gray-200">
Assignments for
<%= link_to @user.name, user_assignments_path(@user), class: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" %>
</h1>
<%= link_to user_assignments_path(@user, format: 'ics'), class: "btn btn-info-light ml-4" do %>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 24" fill="currentColor" aria-hidden="true" class="size-5 inline-block mr-1"><path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd"></path></svg> iCal
<% end %>
</div>
</div>
<div class="overflow-x-auto max-w-full">
<h2 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-4 sticky left-0">Table View</h2>
<div class="bg-white dark:bg-gray-800 shadow overflow-hidden rounded-lg">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Date</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Starts</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Ends</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Stage</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Session</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Collaborators</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
<% @user.assignments.includes(:session, session: :conference).order('sessions.starts_at').each do |assignment| %>
<tr class="<%= assignment.session.ends_at < Time.now ? "past" : "future" %>">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.starts_at.strftime('%Y-%m-%d') %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.starts_at.strftime('%H:%M') %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.ends_at.strftime('%H:%M') %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.stage.name %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-200">
<%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %>
<%= link_to assignment.session.title, assignment.session.url, target: "_blank", class: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" %>
<%= render partial: 'shared/session_engelsystem', locals: { session: assignment.session } %>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
<% assignment.session.assignments.map(&:user).each do |other_user| %>
<%= render partial: 'application/user_avatar', locals: { user: other_user } %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% now = Time.now %>
<!-- Tab Navigation -->
<div class="border-b border-gray-200 dark:border-gray-700 mb-6">
<ul class="flex flex-wrap -mb-px" id="viewTabs" role="tablist">
<li class="mr-2" role="presentation">
<button class="inline-block py-3 px-4 text-blue-600 dark:text-blue-500 font-medium rounded-t-lg border-b-2 border-blue-600 dark:border-blue-500 active"
id="list-tab"
data-tabs-target="#listViewTab"
type="button"
role="tab"
aria-controls="listViewTab"
aria-selected="true">
List View
</button>
</li>
<li class="mr-2" role="presentation">
<button class="inline-block py-3 px-4 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 font-medium rounded-t-lg border-b-2 border-transparent hover:border-gray-300 dark:hover:border-gray-600"
id="table-tab"
data-tabs-target="#tableViewTab"
type="button"
role="tab"
aria-controls="tableViewTab"
aria-selected="false">
Table View
</button>
</li>
</ul>
</div>
<!-- Tab Content -->
<div id="tabContent" style="min-height: calc(100vh - 220px);">
<!-- List View Tab -->
<div class="block" id="listViewTab" role="tabpanel" aria-labelledby="list-tab">
<div class="bg-white dark:bg-gray-800 shadow rounded-lg p-6 overflow-auto" style="max-height: calc(100vh - 220px);">
<% @user.assignments.includes(:session, session: :conference).order('sessions.starts_at').group_by { |a| a.session.starts_at.strftime('%Y-%m-%d') }.each do |date, assignments_on_date| %>
<%= render partial: 'listview_date', locals: { assignments_on_date:, date:, now: } %>
<% end %>
</div>
</div>
<!-- Table View Tab -->
<div class="hidden" id="tableViewTab" role="tabpanel" aria-labelledby="table-tab">
<div class="bg-white dark:bg-gray-800 shadow overflow-hidden rounded-lg">
<div class="overflow-auto" style="max-height: calc(100vh - 220px);">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead>
<tr>
<th scope="col" class="sticky top-0 bg-gray-50 dark:bg-gray-700 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider z-10">Date</th>
<th scope="col" class="sticky top-0 bg-gray-50 dark:bg-gray-700 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider z-10">Starts</th>
<th scope="col" class="sticky top-0 bg-gray-50 dark:bg-gray-700 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider z-10">Ends</th>
<th scope="col" class="sticky top-0 bg-gray-50 dark:bg-gray-700 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider z-10">Stage</th>
<th scope="col" class="sticky top-0 bg-gray-50 dark:bg-gray-700 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider z-10">Session</th>
<th scope="col" class="sticky top-0 bg-gray-50 dark:bg-gray-700 px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider z-10">Collaborators</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
<% @user.assignments.includes(:session, session: :conference).order('sessions.starts_at').each do |assignment| %>
<tr class="<%= assignment.session.ends_at < Time.now ? "past" : "future" %>">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.starts_at.strftime('%Y-%m-%d') %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.starts_at.strftime('%H:%M') %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.ends_at.strftime('%H:%M') %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><%= assignment.session.stage.name %></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-200">
<%= render partial: 'shared/session_filedrop', locals: { session: assignment.session } %>
<%= link_to assignment.session.title, assignment.session.url, target: "_blank", class: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" %>
<%= render partial: 'shared/session_engelsystem', locals: { session: assignment.session } %>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
<% assignment.session.assignments.map(&:user).each do |other_user| %>
<%= render partial: 'application/user_avatar', locals: { user: other_user } %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tabButtons = document.querySelectorAll('[data-tabs-target]');
const tabContents = document.querySelectorAll('[role="tabpanel"]');
tabButtons.forEach(button => {
button.addEventListener('click', () => {
const target = document.querySelector(button.dataset.tabsTarget);
// Hide all tabs
tabContents.forEach(content => {
content.classList.add('hidden');
content.classList.remove('block');
});
// Remove active state from all buttons
tabButtons.forEach(btn => {
btn.classList.remove('text-blue-600', 'dark:text-blue-500', 'border-blue-600', 'dark:border-blue-500', 'active');
btn.classList.add('text-gray-500', 'dark:text-gray-400', 'border-transparent');
btn.setAttribute('aria-selected', 'false');
});
// Show the selected tab
target.classList.remove('hidden');
target.classList.add('block');
// Set active state on clicked button
button.classList.remove('text-gray-500', 'dark:text-gray-400', 'border-transparent');
button.classList.add('text-blue-600', 'dark:text-blue-500', 'border-blue-600', 'dark:border-blue-500', 'active');
button.setAttribute('aria-selected', 'true');
});
});
});
</script>
<h2>Resend confirmation instructions</h2>
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>
<div class="actions">
<%= f.submit "Resend confirmation instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<p>Welcome <%= @email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
<p>Hello <%= @email %>!</p>
<% if @resource.try(:unconfirmed_email?) %>
<p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
<p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
<% end %>
<p>Hello <%= @resource.email %>!</p>
<p>We're contacting you to notify you that your password has been changed.</p>
<p>Hello <%= @resource.email %>!</p>
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
<p>Hello <%= @resource.email %>!</p>
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
<p>Click the link below to unlock your account:</p>
<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
<div class="container mx-auto px-4 py-8">
<div class="max-w-md mx-auto bg-white dark:bg-gray-800 shadow rounded-lg p-6">
<h1 class="text-2xl font-bold mb-6 dark:text-white">Change your password</h1>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<%= f.hidden_field :reset_password_token %>
<div class="mb-4">
<%= f.label :password, "New password", class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<% if @minimum_password_length %>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-2">(<%= @minimum_password_length %> characters minimum)</p>
<% end %>
<%= f.password_field :password, autofocus: true, autocomplete: "new-password", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
<div class="mb-4">
<%= f.label :password_confirmation, "Confirm new password", class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
<div class="mb-6">
<%= f.submit "Change my password", class: "w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
</div>
</div>
<div class="container mx-auto px-4 py-8">
<div class="max-w-md mx-auto bg-white dark:bg-gray-800 shadow rounded-lg p-6">
<h1 class="text-2xl font-bold mb-6 dark:text-white">Forgot your password?</h1>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="mb-4">
<%= f.label :email, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
<div class="mb-6">
<%= f.submit "Send me reset password instructions", class: "w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
</div>
</div>
......@@ -22,27 +22,42 @@
<% end %>
<div class="mb-4">
<%= f.label :password, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-2">(leave blank if you don't want to change it)</p>
<%= f.password_field :password, autocomplete: "new-password", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
<% if @minimum_password_length %>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1"><%= @minimum_password_length %> characters minimum</p>
<% end %>
</div>
<div class="mb-4">
<%= f.label :password_confirmation, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
<div class="mb-4">
<%= f.label :darkmode, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.select :darkmode, User.darkmodes.keys.map { |d| [d.humanize, d] }, {}, class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
<button type="button" id="togglePasswordFields" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-md mb-4">
Change Password
</button>
<div id="passwordFields" class="hidden space-y-4 mt-4 p-4 border border-gray-200 dark:border-gray-700 rounded-md">
<div>
<%= f.label :password, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-2">(leave blank if you don't want to change it)</p>
<%= f.password_field :password, autocomplete: "new-password", autocomplete: "off", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
<% if @minimum_password_length %>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1"><%= @minimum_password_length %> characters minimum</p>
<% end %>
</div>
<div>
<%= f.label :password_confirmation, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.password_field :password_confirmation, autocomplete: "off", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
</div>
</div>
<div class="mb-4">
<%= f.label :avatar_color, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.color_field :avatar_color, class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500" %>
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-3">Appearance Settings</h3>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex-1">
<%= f.label :darkmode, "Theme Preference", class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.select :darkmode, User.darkmodes.keys.map { |d| [d.humanize, d] }, {}, class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Choose your preferred theme appearance</p>
</div>
<div class="flex-1">
<%= f.label :avatar_color, "Profile Color", class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.color_field :avatar_color, class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500" %>
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Select a color for your avatar/profile</p>
</div>
</div>
</div>
<div class="hidden">
......@@ -50,21 +65,29 @@
<%= f.text_field :telegram_username, class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
<fieldset class="mb-4 border border-gray-300 dark:border-gray-600 p-4 rounded-md">
<legend class="text-lg font-semibold text-gray-700 dark:text-gray-300 px-2">More Languages Team Only</legend>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-2">Please use comma-separated two-letter codes.</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">Leave empty unless you are with the more languages team.</p>
<div class="mb-4">
<%= f.label :languages_from, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.text_field :languages_from, placeholder: "de,en", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
<div class="mb-4">
<%= f.label :languages_to, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.text_field :languages_to, placeholder: "jp,es", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
<div class="mb-4">
<button type="button" id="toggleLanguagesFields" class="flex items-center justify-between w-full px-4 py-2 bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-md mb-4">
<span class="text-lg font-semibold">More Languages Team Only</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 transform transition-transform" viewBox="0 0 20 20" fill="currentColor" id="languagesArrow">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
<div id="languagesFields" class="hidden space-y-4 mt-4 p-4 border border-gray-200 dark:border-gray-700 rounded-md">
<p class="text-sm text-gray-500 dark:text-gray-400">Please use comma-separated two-letter codes.</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">Leave empty unless you are with the more languages team.</p>
<div class="mb-4">
<%= f.label :languages_from, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.text_field :languages_from, placeholder: "de,en", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
<div class="mb-4">
<%= f.label :languages_to, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
<%= f.text_field :languages_to, placeholder: "jp,es", class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white" %>
</div>
</div>
</fieldset>
</div>
<div class="mb-6">
<%= f.label :current_password, class: "block text-gray-700 dark:text-gray-300 mb-2" %>
......@@ -84,3 +107,33 @@
<%= link_to "Back", :back, class: "inline-block text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 mt-4" %>
</div>
</div>
<script>
// Toggle password fields
document.addEventListener('DOMContentLoaded', function() {
const togglePasswordBtn = document.getElementById('togglePasswordFields');
const passwordFields = document.getElementById('passwordFields');
togglePasswordBtn.addEventListener('click', function() {
passwordFields.classList.toggle('hidden');
});
// Toggle languages fields
const toggleLanguagesBtn = document.getElementById('toggleLanguagesFields');
const languagesFields = document.getElementById('languagesFields');
const languagesArrow = document.getElementById('languagesArrow');
toggleLanguagesBtn.addEventListener('click', function() {
languagesFields.classList.toggle('hidden');
languagesArrow.classList.toggle('rotate-180');
});
// Disable autocomplete for password fields
const passwordInputs = document.querySelectorAll('input[type="password"]');
passwordInputs.forEach(input => {
input.setAttribute('autocomplete', 'new-password');
// Add a random name attribute to further prevent autocomplete
input.setAttribute('name', input.getAttribute('name') + '_' + Math.random().toString(36).substring(2));
});
});
</script>
<% if resource.errors.any? %>
<div id="error_explanation" data-turbo-cache="false" class="bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 text-red-800 dark:text-red-200 px-4 py-3 rounded mb-4">
<h2 class="text-lg font-medium">
<%= I18n.t("errors.messages.not_saved",
count: resource.errors.count,
resource: resource.class.model_name.human.downcase)
%>
</h2>
<ul class="list-disc list-inside mt-2">
<% resource.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<h2>Resend unlock instructions</h2>
<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="actions">
<%= f.submit "Resend unlock instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<!DOCTYPE html>
<html class="<%= "dark" if current_user&.darkmode == "dark"%>">
<html class="<%= current_user&.darkmode || "auto" %>">
<head>
<title>re:scheduled</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
......@@ -9,6 +9,26 @@
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
<script>
(function() {
if (!document.documentElement.classList.contains('dark') &&
!document.documentElement.classList.contains('light')) {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.add('light');
}
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
if (!localStorage.getItem('theme')) {
document.documentElement.classList.remove('dark', 'light');
document.documentElement.classList.add(e.matches ? 'dark' : 'light');
}
});
})();
</script>
</head>
<body <%= tag.attributes(body_data_attributes) %> class="bg-gray-100 dark:bg-gray-900 min-h-screen">
......@@ -41,9 +61,9 @@
</div>
<% else %>
<div class="flex items-center space-x-4">
<span class="px-2 text-gray-600 dark:text-gray-400">not logged in</span>
<%= link_to "Login", new_user_session_path, class: "hover:text-gray-900 dark:hover:text-slate-200" %>
<%= link_to "Sign Up", new_user_registration_path, class: "hover:text-gray-900 dark:hover:text-slate-200" %>
<span class="px-2 text-gray-600 dark:text-gray-300">not logged in</span>
<%= link_to "Log in", new_user_session_path, class: "text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white" %>
<%= link_to "Sign Up", new_user_registration_path, class: "text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white" %>
</div>
<% end %>
</nav>
......@@ -52,17 +72,19 @@
<main>
<% if notice %>
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4 mx-4 mt-4" role="alert">
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4 mx-4 mt-4
dark:bg-green-900 dark:border-green-600 dark:text-green-300" role="alert">
<span class="block sm:inline"><%= notice %></span>
</div>
<% end %>
<% if alert %>
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4 mx-4 mt-4" role="alert">
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4 mx-4 mt-4
dark:bg-red-900 dark:border-red-600 dark:text-red-300" role="alert">
<span class="block sm:inline"><%= alert %></span>
</div>
<% end %>
<%= yield %>
</main>
</body>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment