Changed item#_form input user/room
This commit is contained in:
65
app/javascript/controllers/autocomplete_controller.js
Normal file
65
app/javascript/controllers/autocomplete_controller.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["input", "results", "item"]
|
||||
|
||||
connect() {
|
||||
// Schließt die Liste, wenn man irgendwo außerhalb hinklickt
|
||||
this.closeHandler = (e) => {
|
||||
if (!this.element.contains(e.target)) {
|
||||
this.hideResults()
|
||||
}
|
||||
}
|
||||
document.addEventListener("click", this.closeHandler)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
document.removeEventListener("click", this.closeHandler)
|
||||
}
|
||||
|
||||
// Wird aufgerufen, wenn der Nutzer tippt (input-Event)
|
||||
filter() {
|
||||
const filterValue = this.inputTarget.value.toLowerCase().trim()
|
||||
|
||||
if (filterValue === "") {
|
||||
this.showAll()
|
||||
return
|
||||
}
|
||||
|
||||
this.showResults()
|
||||
let hasMatches = false
|
||||
|
||||
this.itemTargets.forEach(item => {
|
||||
const text = item.textContent.toLowerCase()
|
||||
if (text.includes(filterValue)) {
|
||||
item.classList.remove("hidden")
|
||||
hasMatches = true
|
||||
} else {
|
||||
item.classList.add("hidden")
|
||||
}
|
||||
})
|
||||
|
||||
// Falls gar nichts gefunden wird, blenden wir die Liste aus
|
||||
if (!hasMatches) this.hideResults()
|
||||
}
|
||||
|
||||
// Ein Klick auf einen Eintrag wählt ihn aus
|
||||
select(event) {
|
||||
const value = event.currentTarget.dataset.value
|
||||
this.inputTarget.value = value
|
||||
this.hideResults()
|
||||
}
|
||||
|
||||
showResults() {
|
||||
this.resultsTarget.classList.remove("hidden")
|
||||
}
|
||||
|
||||
hideResults() {
|
||||
this.resultsTarget.classList.add("hidden")
|
||||
}
|
||||
|
||||
showAll() {
|
||||
this.showResults()
|
||||
this.itemTargets.forEach(item => item.classList.remove("hidden"))
|
||||
}
|
||||
}
|
||||
@@ -134,55 +134,73 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Live-Suche (Reiner Text, keine versteckten IDs) -->
|
||||
<!-- Live-Suche (Mobil-optimierter Autocomplete-Ersatz für Datalist) -->
|
||||
<div class="mt-4">
|
||||
<% if type == "user" %>
|
||||
<!-- Signalisiert Rails, dass die room_id gelöscht werden soll -->
|
||||
<input type="hidden" name="item[room_id]" value="">
|
||||
|
||||
<label for="item_user_name" class="block text-sm font-medium mb-1.5 text-gray-700">Mitarbeiter suchen (Vorname, Nachname oder E-Mail)...</label>
|
||||
<div class="relative">
|
||||
<!-- Wir senden den Klartext-Namen an ein virtuelles Feld 'user_name' -->
|
||||
<label for="item_user_name" class="block text-sm font-medium mb-1.5 text-gray-700">Mitarbeiter suchen (Vorname, Nachname)...</label>
|
||||
|
||||
<!-- STIMULUS CONTAINER FÜR USER -->
|
||||
<div class="relative" data-controller="autocomplete">
|
||||
<input type="text"
|
||||
id="item_user_name"
|
||||
name="item[user_name]"
|
||||
list="users_datalist"
|
||||
value="<%= item.user&.name %>"
|
||||
data-autocomplete-target="input"
|
||||
data-action="input->autocomplete#filter focus->autocomplete#showAll"
|
||||
class="py-2.5 px-3 block w-full border border-gray-300 rounded-lg text-sm bg-white focus:border-blue-500 focus:ring-blue-500"
|
||||
placeholder="Tippe den Namen ein...">
|
||||
placeholder="Tippe den Namen ein..."
|
||||
autocomplete="off">
|
||||
|
||||
<datalist id="users_datalist">
|
||||
<!-- DIE NEUE MOBILE ERGEBNIS-LISTE -->
|
||||
<div data-autocomplete-target="results" class="hidden absolute z-50 left-0 right-0 mt-1 max-h-60 overflow-y-auto bg-white border border-gray-200 rounded-lg shadow-lg divide-y divide-gray-100">
|
||||
<% User.all.order(:first_name, :last_name).each do |user| %>
|
||||
<!-- Hier nutzen wir den reinen Vor- und Nachnamen als Value -->
|
||||
<option value="<%= user.name %>"></option>
|
||||
<div data-autocomplete-target="item"
|
||||
data-action="click->autocomplete#select"
|
||||
data-value="<%= user.name %>"
|
||||
class="px-4 py-2.5 text-sm text-gray-800 hover:bg-blue-50 cursor-pointer transition flex items-center gap-2">
|
||||
<!-- Kleines Symbol für visuelles Feedback -->
|
||||
<svg class="h-4 w-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg>
|
||||
<%= user.name %>
|
||||
</div>
|
||||
<% end %>
|
||||
</datalist>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% elsif type == "room" %>
|
||||
<!-- Signalisiert Rails, dass die user_id gelöscht werden soll -->
|
||||
<input type="hidden" name="item[user_id]" value="">
|
||||
|
||||
<label for="item_room_name" class="block text-sm font-medium mb-1.5 text-gray-700">Raum suchen (Raumnummer)...</label>
|
||||
<div class="relative">
|
||||
<!-- Wir senden den Klartext-Namen an ein virtuelles Feld 'room_name' -->
|
||||
|
||||
<!-- STIMULUS CONTAINER FÜR RÄUME -->
|
||||
<div class="relative" data-controller="autocomplete">
|
||||
<input type="text"
|
||||
id="item_room_name"
|
||||
name="item[room_name]"
|
||||
list="rooms_datalist"
|
||||
value="<%= item.room&.name %>"
|
||||
data-autocomplete-target="input"
|
||||
data-action="input->autocomplete#filter focus->autocomplete#showAll"
|
||||
class="py-2.5 px-3 block w-full border border-gray-300 rounded-lg text-sm bg-white focus:border-blue-500 focus:ring-blue-500"
|
||||
placeholder="Tippe die Raumnummer ein...">
|
||||
placeholder="Tippe die Raumnummer ein..."
|
||||
autocomplete="off">
|
||||
|
||||
<datalist id="rooms_datalist">
|
||||
<!-- DIE NEUE MOBILE ERGEBNIS-LISTE -->
|
||||
<div data-autocomplete-target="results" class="hidden absolute z-50 left-0 right-0 mt-1 max-h-60 overflow-y-auto bg-white border border-gray-200 rounded-xl shadow-lg divide-y divide-gray-100">
|
||||
<% Room.all.order(:name).each do |room| %>
|
||||
<option value="<%= room.name %>"></option>
|
||||
<div data-autocomplete-target="item"
|
||||
data-action="click->autocomplete#select"
|
||||
data-value="<%= room.name %>"
|
||||
class="px-4 py-2.5 text-sm text-gray-800 hover:bg-blue-50 cursor-pointer transition flex items-center gap-2">
|
||||
<svg class="h-4 w-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25s-7.5-4.108-7.5-11.25a7.5 7.5 0 1 1 15 0Z" /></svg>
|
||||
<div class="font-medium"><%= room.name %></div>
|
||||
<div class="text-xs text-gray-400 font-normal ml-auto"><%= room.building %></div>
|
||||
</div>
|
||||
<% end %>
|
||||
</datalist>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% else %>
|
||||
<!-- Hauptlager gewählt -> Beide IDs nullen -->
|
||||
<input type="hidden" name="item[user_id]" value="">
|
||||
<input type="hidden" name="item[room_id]" value="">
|
||||
<div class="p-4 rounded-lg border border-dashed border-gray-200 bg-gray-50/50 text-center text-xs text-gray-500">
|
||||
@@ -190,6 +208,7 @@
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user