Skip to content

Commit

Permalink
Preserve search input state after search request
Browse files Browse the repository at this point in the history
  • Loading branch information
abdokin committed Nov 5, 2024
1 parent b490d19 commit bc331ab
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 105 deletions.
3 changes: 2 additions & 1 deletion app/components/filter_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<%= form_with url: filter_url, method: :get, data: { controller: "search", search_target: "form", "turbo-frame": "filter_result", infinite_scroll_target: "filterForm" } do |form| %>
<%= form_with url: filter_url, method: :get,
data: { controller: "search", search_target: "form", "turbo-frame": "filter_result", infinite_scroll_target: "filterForm" } do |form| %>
<%= render SearchInputComponent.new(form:, placeholder:) %>

<h2 class="pt-7 text-xl font-bold text-black"><%= t('.filters') %></h2>
Expand Down
1 change: 1 addition & 0 deletions app/components/search_input_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
placeholder: placeholder,
class: "primary-field rounded-xl py-2.5 pr-5 pl-10 text-sm bg-white mt-0",
value: params[:search_query],
id: "search_input",
data: {
search_target: "input",
action: "input->search#search"
Expand Down
19 changes: 17 additions & 2 deletions app/javascript/controllers/search_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,27 @@ export default class extends Controller {
this.timeout = null
}

search() {
search(event) {

const input = event.target
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
const cursorPosition = input.selectionStart
const inputValue = input.value
console.log("search");

this.formTarget.requestSubmit()

document.addEventListener('turbo:frame-render', () => {
const searchInput = document.getElementById("search_input")
if (searchInput) {
searchInput.value = inputValue
searchInput.focus()
searchInput.setSelectionRange(cursorPosition, cursorPosition)
}
}, { once: true })
}, 300)
}
}

submitOnCheck() {
this.formTarget.requestSubmit()
Expand Down
176 changes: 93 additions & 83 deletions app/views/assessments/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,102 +11,112 @@
<% end %>
</div>
</div>
<div class="pt-2 sm:pt-5 pb-5 flex flex-col md:flex-row md:justify-between md:items-center gap-x-20 gap-y-6">
<div class="w-full md:max-w-sm h-fit">
<%= form_with url: assessments_path, method: :get, data: { controller: "search", search_target: "form" } do |form| %>
<%= render SearchInputComponent.new(form:, placeholder: t('.search_placeholder')) %>
<% params.permit(:page, :per_page, :state).to_h.each do |key, value| %>
<%= form.hidden_field key, value: value %>
<%= turbo_frame_tag "assessments_list" do %>
<div class="pt-2 sm:pt-5 pb-5 flex flex-col md:flex-row md:justify-between md:items-center gap-x-20 gap-y-6">
<div class="w-full md:max-w-sm h-fit">
<%= form_with(
url: assessments_path,
method: :get,
data: {
controller: "search",
search_target: "form",
turbo_frame: "assessments_list"
}
) do |form| %>
<%= render SearchInputComponent.new(form:, placeholder: t('.search_placeholder')) %>
<% params.permit(:page, :per_page, :state).to_h.each do |key, value| %>
<%= form.hidden_field key, value: value %>
<% end %>
<% end %>
<% end %>
</div>
<span class="md:whitespace-nowrap isolate max-md:grid max-md:grid-cols-3 md:flex rounded-md shadow-sm border border-gray-800 divide-x divide-gray-800 bg-white">
<%= link_to assessments_path(params.permit(:page, :per_page, :search_query).merge(state: 'active')), class: "inline-flex justify-center md:w-[120px] relative rounded-l-md px-3 sm:px-5 py-3 text-xs sm:text-sm font-#{@state == 'active' ? 'bold' : 'semibold'} text-gray-900 #{@state == 'active' ? 'bg-blue-50' : 'hover:bg-gray-50'} focus:z-10" do %>
<%= t('.active', count: @filtered_assessments.active.count) %>
<% end %>
<%= link_to assessments_path(state: 'inactive'), class: "inline-flex justify-center md:w-[124px] relative px-3 sm:px-5 py-3 text-xs sm:text-sm font-#{@state == 'inactive' ? 'bold' : 'semibold'} text-gray-900 #{@state == 'inactive' ? 'bg-blue-50' : 'hover:bg-gray-50'} focus:z-10" do %>
<%= t('.inactive', count: @filtered_assessments.inactive.count) %>
<% end %>
<%= link_to assessments_path(params.permit(:page, :per_page, :search_query).merge(state: 'archived')), class: "inline-flex justify-center md:w-[130px] relative rounded-r-md px-3 sm:px-5 py-3 text-xs sm:text-sm font-#{@state == 'archived' ? 'bold' : 'semibold'} text-gray-900 #{@state == 'archived' ? 'bg-blue-50' : 'hover:bg-gray-50'} focus:z-10" do %>
<%= t('.archived', count: @filtered_assessments.archived.count) %>
<% end %>
</span>
</div>
<span class="md:whitespace-nowrap isolate max-md:grid max-md:grid-cols-3 md:flex rounded-md shadow-sm border border-gray-800 divide-x divide-gray-800 bg-white">
<%= link_to assessments_path(params.permit(:page, :per_page, :search_query).merge(state: 'active')), class: "inline-flex justify-center md:w-[120px] relative rounded-l-md px-3 sm:px-5 py-3 text-xs sm:text-sm font-#{@state == 'active' ? 'bold' : 'semibold'} text-gray-900 #{@state == 'active' ? 'bg-blue-50' : 'hover:bg-gray-50'} focus:z-10" do %>
<%= t('.active', count: @filtered_assessments.active.count) %>
<% end %>
<%= link_to assessments_path(state: 'inactive'), class: "inline-flex justify-center md:w-[124px] relative px-3 sm:px-5 py-3 text-xs sm:text-sm font-#{@state == 'inactive' ? 'bold' : 'semibold'} text-gray-900 #{@state == 'inactive' ? 'bg-blue-50' : 'hover:bg-gray-50'} focus:z-10" do %>
<%= t('.inactive', count: @filtered_assessments.inactive.count) %>
<% end %>
<%= link_to assessments_path(params.permit(:page, :per_page, :search_query).merge(state: 'archived')), class: "inline-flex justify-center md:w-[130px] relative rounded-r-md px-3 sm:px-5 py-3 text-xs sm:text-sm font-#{@state == 'archived' ? 'bold' : 'semibold'} text-gray-900 #{@state == 'archived' ? 'bg-blue-50' : 'hover:bg-gray-50'} focus:z-10" do %>
<%= t('.archived', count: @filtered_assessments.archived.count) %>
<% end %>
</span>
</div>
<div class="pb-16">
<div class="border border-gray-200 bg-white rounded-xl">
<div class="flow-root">
<div class="inline-block min-w-full align-middle">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-bold text-gray-800 sm:pl-6"><%= t('.name') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden sm:table-cell"><%= t('.candidates') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden sm:table-cell"><%= t('.progress') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden md:table-cell"><%= t('.last_activity') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden lg:table-cell"><%= t('.date_created') %></th>
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
<span class="sr-only"><%= t('.actions') %></span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<% if @assessments.empty? %>
<div class="pb-16">
<div class="border border-gray-200 bg-white rounded-xl">
<div class="flow-root">
<div class="inline-block min-w-full align-middle">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<td colspan="5"><%= render NoResultsComponent.new %></td>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-bold text-gray-800 sm:pl-6"><%= t('.name') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden sm:table-cell"><%= t('.candidates') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden sm:table-cell"><%= t('.progress') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden md:table-cell"><%= t('.last_activity') %></th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-bold text-gray-800 hidden lg:table-cell"><%= t('.date_created') %></th>
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
<span class="sr-only"><%= t('.actions') %></span>
</th>
</tr>
<% else %>
<% @assessments.each_with_index do |assessment, index| %>
<tr class="hover:bg-blue-50 cursor-pointer"
</thead>
<tbody class="divide-y divide-gray-200">
<% if @assessments.empty? %>
<tr>
<td colspan="5"><%= render NoResultsComponent.new %></td>
</tr>
<% else %>
<% @assessments.each_with_index do |assessment, index| %>
<tr class="hover:bg-blue-50 cursor-pointer"
data-controller="clickable-row"
data-clickable-row-url-value="<%= assessment_path(assessment) %>"
data-action="click->clickable-row#handleClick">
<td class="py-4 pl-4 pr-3 text-sm font-medium text-gray-800 sm:pl-6 max-w-[240px] sm:max-w-xs truncate"><%= assessment.title %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden sm:table-cell"><%= assessment.assessment_participations.count %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden sm:table-cell"><%= display_percentage_or_minus(assessment.progress) %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden md:table-cell"><%= time_ago_in_words(assessment.last_activity) %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden lg:table-cell"><%= human_date assessment.created_at %></td>
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm sm:pr-6">
<div class="ignore dropdown dropdown-hover">
<button tabindex="<%= index %>" type="button" class="text-gray-800 hover:bg-white hover:rounded-full p-0.5">
<%= svg_tag "ellipsis_vertical" %>
</button>
<div tabindex="<%= index %>" class="dropdown-content absolute right-8 -top-4 z-10 mt-2 w-40 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
<div class="py-1" role="none">
<% if assessment.assessment_participations.any? %>
<button type="button" class="group flex items-center gap-x-2.5 px-4 py-2 text-sm text-zinc-400 font-medium">
<%= svg_tag "pencil_square", class: "size-5" %>
<span class="whitespace-nowrap"><%= t('.edit') %></span>
</button>
<% else %>
<%= link_to edit_assessment_path(assessment), class: "group flex items-center gap-x-2.5 px-4 py-2 text-sm text-gray-700 font-medium" do %>
<%= svg_tag "pencil_square", class: "size-5 group-hover:text-gray-500" %>
<span class="whitespace-nowrap"><%= t('.edit') %></span>
<td class="py-4 pl-4 pr-3 text-sm font-medium text-gray-800 sm:pl-6 max-w-[240px] sm:max-w-xs truncate"><%= assessment.title %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden sm:table-cell"><%= assessment.assessment_participations.count %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden sm:table-cell"><%= display_percentage_or_minus(assessment.progress) %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden md:table-cell"><%= time_ago_in_words(assessment.last_activity) %></td>
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-800 hidden lg:table-cell"><%= human_date assessment.created_at %></td>
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm sm:pr-6">
<div class="ignore dropdown dropdown-hover">
<button tabindex="<%= index %>" type="button" class="text-gray-800 hover:bg-white hover:rounded-full p-0.5">
<%= svg_tag "ellipsis_vertical" %>
</button>
<div tabindex="<%= index %>" class="dropdown-content absolute right-8 -top-4 z-10 mt-2 w-40 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
<div class="py-1" role="none">
<% if assessment.assessment_participations.any? %>
<button type="button" class="group flex items-center gap-x-2.5 px-4 py-2 text-sm text-zinc-400 font-medium">
<%= svg_tag "pencil_square", class: "size-5" %>
<span class="whitespace-nowrap"><%= t('.edit') %></span>
</button>
<% else %>
<%= link_to edit_assessment_path(assessment), class: "group flex items-center gap-x-2.5 px-4 py-2 text-sm text-gray-700 font-medium" do %>
<%= svg_tag "pencil_square", class: "size-5 group-hover:text-gray-500" %>
<span class="whitespace-nowrap"><%= t('.edit') %></span>
<% end %>
<% end %>
<% end %>
<%= button_to assessment.archived? ? unarchive_assessment_path(assessment) : archive_assessment_path(assessment), method: :patch, class: "group flex items-center gap-x-2.5 px-4 py-2 text-sm text-gray-700 font-medium" do %>
<%= svg_tag "archive_box", class: "size-5 group-hover:text-gray-500" %>
<%= t(assessment.archived? ? '.unarchive' : '.archive') %>
<% end %>
<%= button_to assessment.archived? ? unarchive_assessment_path(assessment) : archive_assessment_path(assessment), method: :patch, class: "group flex items-center gap-x-2.5 px-4 py-2 text-sm text-gray-700 font-medium" do %>
<%= svg_tag "archive_box", class: "size-5 group-hover:text-gray-500" %>
<%= t(assessment.archived? ? '.unarchive' : '.archive') %>
<% end %>
</div>
</div>
</div>
</div>
</td>
</tr>
</td>
</tr>
<% end %>
<% end %>
<% end %>
</tbody>
</table>
</tbody>
</table>
</div>
</div>
<!-- Pagination -->
<%= render PaginationComponent.new(
article_name: Assessment.model_name.human(count: 2),
current_page: @current_page,
total_items: @total_items,
per_page: @per_page,
additional_params: { state: @state, search_query: params[:search_query] }
) %>
</div>
<!-- Pagination -->
<%= render PaginationComponent.new(
article_name: Assessment.model_name.human(count: 2),
current_page: @current_page,
total_items: @total_items,
per_page: @per_page,
additional_params: { state: @state, search_query: params[:search_query] }
) %>
</div>
</div>
<% end %>
</div>
</main>
39 changes: 20 additions & 19 deletions app/views/customer/candidates/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,25 @@
<% end %>
</div>
</div>
<%= form_with url: customer_candidates_path, method: :get, data: { controller: "search", search_target: "form" } do |form| %>
<div class="pt-2 sm:pt-5 pb-5 flex flex-col sm:flex-row items-center gap-y-4 sm:gap-x-5">
<div class="w-full sm:max-w-xs">
<%= render SearchInputComponent.new(form:, placeholder: t('.search_candidates')) %>
</div>
<select name="assessment_id" onchange="this.form.submit()" class="select-field w-full sm:w-60 py-2.5 sm:py-2 pl-5 pr-10 rounded-xl text-gray-800 border border-gray-800 placeholder:text-gray-400 font-medium focus:border focus:border-gray-800 focus:ring-1 focus:ring-inset focus:ring-gray-800 sm:text-sm sm:leading-6">
<option class="font-medium text-gray-400" value="" selected><%= t('.assessment') %></option>
<% current_business.assessments.each do |assessment| %>
<% active_option = assessment.id.to_s == params[:assessment_id] %>
<option class="font-medium <%= 'bg-zinc-200' if active_option %>" value="<%= assessment.id %>" <%= 'selected' if active_option %>>
<%= truncate(assessment.title, length: 28) %>
</option>
<% end %>
</select>
<%= turbo_frame_tag "candidates" do %>
<%= form_with url: customer_candidates_path, method: :get, data: { controller: "search", search_target: "form" } do |form| %>
<div class="pt-2 sm:pt-5 pb-5 flex flex-col sm:flex-row items-center gap-y-4 sm:gap-x-5">
<div class="w-full sm:max-w-xs">
<%= render SearchInputComponent.new(form:, placeholder: t('.search_candidates')) %>
</div>
<select name="assessment_id" onchange="this.form.submit()" class="select-field w-full sm:w-60 py-2.5 sm:py-2 pl-5 pr-10 rounded-xl text-gray-800 border border-gray-800 placeholder:text-gray-400 font-medium focus:border focus:border-gray-800 focus:ring-1 focus:ring-inset focus:ring-gray-800 sm:text-sm sm:leading-6">
<option class="font-medium text-gray-400" value="" selected><%= t('.assessment') %></option>
<% current_business.assessments.each do |assessment| %>
<% active_option = assessment.id.to_s == params[:assessment_id] %>
<option class="font-medium <%= 'bg-zinc-200' if active_option %>" value="<%= assessment.id %>" <%= 'selected' if active_option %>>
<%= truncate(assessment.title, length: 28) %>
</option>
<% end %>
</select>
</div>
<% params.permit(:page, :per_page).to_h.each do |key, value| %>
<%= form.hidden_field key, value: value %>
<% end %>
<% params.permit(:page, :per_page).to_h.each do |key, value| %>
<%= form.hidden_field key, value: value %>
<% end %>
<% end %>
<div class="pb-16">
<div class="border border-gray-200 bg-white rounded-xl">
Expand Down Expand Up @@ -81,5 +82,5 @@
) %>
</div>
</div>
</div>
</main>
<% end %>
</main>

0 comments on commit bc331ab

Please sign in to comment.