mirror of
https://github.com/indentlabs/notebook.git
synced 2025-10-26 11:19:22 +00:00
final folder#show polish
This commit is contained in:
parent
c931356f22
commit
a0ddca75bf
@ -2,7 +2,7 @@
|
||||
showNewFolderModal: false,
|
||||
showEditFolderModal: false,
|
||||
sidebarOpen: false,
|
||||
showContentSidebar: false,
|
||||
showContentSidebar: <%= @child_folders.any? || @content.any? %>,
|
||||
viewMode: 'grid',
|
||||
searchQuery: ''
|
||||
}" class="h-screen flex bg-gray-50">
|
||||
@ -207,8 +207,60 @@
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<main class="flex-1 flex flex-col overflow-hidden lg:pt-0 pt-16" :class="{ 'lg:ml-0': !showContentSidebar }">
|
||||
<!-- Breadcrumb Navigation -->
|
||||
<nav class="bg-white border-b border-gray-200 px-6 lg:px-8 py-3">
|
||||
<ol class="flex items-center space-x-2 text-sm">
|
||||
<%
|
||||
breadcrumb_folders = []
|
||||
current_folder = @folder
|
||||
|
||||
while current_folder&.parent_folder
|
||||
breadcrumb_folders.unshift(current_folder.parent_folder)
|
||||
current_folder = current_folder.parent_folder
|
||||
end
|
||||
%>
|
||||
|
||||
<li>
|
||||
<%
|
||||
context_class = @folder.context.constantize rescue Document
|
||||
if context_class.column_names.include?('folder_id')
|
||||
context_path = context_class.name.downcase.pluralize + "_path"
|
||||
context_name = @folder.context.pluralize
|
||||
else
|
||||
context_path = "documents_path"
|
||||
context_name = "Documents"
|
||||
end
|
||||
%>
|
||||
<%= link_to send(context_path), class: "text-gray-500 hover:text-gray-700 hover:underline" do %>
|
||||
<%= context_name %>
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<li class="text-gray-400">
|
||||
<i class="material-icons text-sm">chevron_right</i>
|
||||
</li>
|
||||
|
||||
<% breadcrumb_folders.each do |folder| %>
|
||||
<li>
|
||||
<%= link_to folder.title, folder, class: "text-gray-500 hover:text-gray-700 hover:underline truncate max-w-[150px]" %>
|
||||
</li>
|
||||
<li class="text-gray-400">
|
||||
<i class="material-icons text-sm">chevron_right</i>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<li class="font-medium text-gray-900 truncate max-w-[200px]">
|
||||
<%= @folder.title %>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<!-- Header Section -->
|
||||
<div class="bg-white shadow-sm">
|
||||
<div class="relative">
|
||||
<%= image_tag asset_path("card-headers/folders.jpg"), class: 'h-32 w-full object-cover lg:h-48' %>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-black/40 to-black/20"></div>
|
||||
</div>
|
||||
<div class="px-6 lg:px-8 py-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-4">
|
||||
@ -248,9 +300,13 @@
|
||||
<div class="flex items-center">
|
||||
<button
|
||||
@click="showEditFolderModal = true"
|
||||
class="w-12 h-12 rounded-lg <%= Folder.color %> flex items-center justify-center mr-3"
|
||||
class="w-12 h-12 rounded-lg <%= Folder.color %> flex items-center justify-center mr-3 hover:shadow-lg transition-shadow duration-200 group relative"
|
||||
title="Edit folder"
|
||||
>
|
||||
<i class="material-icons text-white text-xl"><%= Folder.icon %></i>
|
||||
<span class="absolute -bottom-2 -right-2 w-6 h-6 bg-white rounded-full shadow flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<i class="material-icons text-gray-600 text-sm">edit</i>
|
||||
</span>
|
||||
</button>
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900"><%= @folder.title %></h1>
|
||||
@ -266,15 +322,39 @@
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<button
|
||||
@click="showNewFolderModal = true"
|
||||
class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg text-white <%= Folder.color %> hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-sm"
|
||||
class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg text-white <%= Folder.color %> hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-sm transition-all duration-150 hover:shadow-md"
|
||||
>
|
||||
<i class="material-icons text-lg mr-2">create_new_folder</i>
|
||||
<span class="hidden sm:inline">New subfolder</span>
|
||||
<span class="sm:hidden">New</span>
|
||||
</button>
|
||||
|
||||
<div class="relative" data-controller="dropdown">
|
||||
<button
|
||||
data-action="dropdown#toggle click@window->dropdown#hide"
|
||||
class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg text-gray-700 bg-white border border-gray-300 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-sm transition-all duration-150"
|
||||
>
|
||||
<i class="material-icons text-lg mr-2">more_horiz</i>
|
||||
<span class="hidden sm:inline">Actions</span>
|
||||
</button>
|
||||
<div data-dropdown-target="menu" class="hidden absolute right-0 mt-2 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 py-1 z-10">
|
||||
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
<i class="material-icons text-sm mr-2 align-text-bottom">drive_file_move</i>
|
||||
Move folder
|
||||
</a>
|
||||
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
<i class="material-icons text-sm mr-2 align-text-bottom">content_copy</i>
|
||||
Duplicate folder
|
||||
</a>
|
||||
<a href="#" class="block px-4 py-2 text-sm text-red-600 hover:bg-red-50">
|
||||
<i class="material-icons text-sm mr-2 align-text-bottom">delete</i>
|
||||
Delete folder
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -286,8 +366,8 @@
|
||||
<h2 class="text-lg font-medium text-gray-900 mb-4">Folders</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 mb-8">
|
||||
<% @child_folders.each do |folder| %>
|
||||
<%= link_to folder, class: "bg-white rounded-lg border border-gray-200 hover:shadow-md transition-shadow duration-200 p-4 flex items-center" do %>
|
||||
<div class="w-10 h-10 rounded-lg <%= Folder.color %> flex items-center justify-center mr-3 flex-shrink-0">
|
||||
<%= link_to folder, class: "bg-white rounded-lg border border-gray-200 hover:shadow-lg hover:-translate-y-1 transition-all duration-200 p-4 flex items-center group" do %>
|
||||
<div class="w-10 h-10 rounded-lg <%= Folder.color %> flex items-center justify-center mr-3 flex-shrink-0 group-hover:shadow-md transition-shadow">
|
||||
<i class="material-icons text-white"><%= Folder.icon %></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
@ -313,7 +393,7 @@
|
||||
<p class="text-sm text-gray-500">Empty folder</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<i class="material-icons text-gray-400">chevron_right</i>
|
||||
<i class="material-icons text-gray-400 group-hover:text-gray-600 transition-colors">chevron_right</i>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@ -322,7 +402,10 @@
|
||||
<!-- Content Section -->
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-lg font-medium text-gray-900">Contents <span class="text-gray-500"><%= @content.count %></span></h2>
|
||||
<div class="flex items-center space-x-3">
|
||||
<h2 class="text-lg font-medium text-gray-900">Contents</h2>
|
||||
<span class="text-sm font-medium px-2.5 py-0.5 rounded-full bg-gray-100 text-gray-800"><%= @content.count %></span>
|
||||
</div>
|
||||
|
||||
<!-- Search and Filter Controls -->
|
||||
<% if @content.any? %>
|
||||
@ -331,12 +414,26 @@
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i class="material-icons text-gray-400 text-lg">search</i>
|
||||
</div>
|
||||
<input
|
||||
x-model="searchQuery"
|
||||
type="text"
|
||||
placeholder="Search contents..."
|
||||
class="block w-64 pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
/>
|
||||
<div class="relative group" x-data="{ isSearching: false }">
|
||||
<input
|
||||
x-model="searchQuery"
|
||||
@input="isSearching = true; setTimeout(() => { isSearching = false }, 300)"
|
||||
type="text"
|
||||
placeholder="Search contents..."
|
||||
class="block w-64 pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
/>
|
||||
<div class="absolute inset-y-0 right-0 pr-3 flex items-center">
|
||||
<button x-show="searchQuery.length > 0" @click="searchQuery = ''" class="text-gray-400 hover:text-gray-600">
|
||||
<i class="material-icons text-lg">clear</i>
|
||||
</button>
|
||||
<div x-show="isSearching" class="animate-spin h-4 w-4 border-2 border-blue-500 rounded-full border-t-transparent"></div>
|
||||
</div>
|
||||
|
||||
<!-- Keyboard shortcut hint -->
|
||||
<div class="absolute top-full left-0 mt-2 px-2 py-1 bg-gray-800 text-white text-xs rounded opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none whitespace-nowrap z-10">
|
||||
Press <kbd class="px-1 py-0.5 bg-gray-700 rounded">⌘K</kbd> to focus search
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- View Mode Toggle -->
|
||||
@ -353,12 +450,56 @@
|
||||
</div>
|
||||
|
||||
<% if @content.any? %>
|
||||
<!-- Search Empty State -->
|
||||
<div x-show="searchQuery !== ''" x-transition class="hidden" id="search-empty-state">
|
||||
<div class="flex-1 flex items-center justify-center p-12 min-h-96">
|
||||
<div class="text-center max-w-lg">
|
||||
<div class="mx-auto h-24 w-24 rounded-full bg-gradient-to-br from-gray-100 to-gray-200 flex items-center justify-center mb-6 shadow-sm">
|
||||
<i class="material-icons text-4xl text-gray-400">search_off</i>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-3">No matching items found</h3>
|
||||
<p class="text-gray-600 mb-8 leading-relaxed" x-text="`We couldn't find any items matching '${searchQuery}'. Try adjusting your search terms.`"></p>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<button @click="searchQuery = ''" class="inline-flex items-center px-6 py-3 text-sm font-medium rounded-lg text-gray-700 bg-white border border-gray-300 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors shadow-sm">
|
||||
<i class="material-icons text-lg mr-2">clear</i>
|
||||
Clear search
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Grid View -->
|
||||
<div x-show="viewMode === 'grid'" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
<% @content.each do |content_item| %>
|
||||
<div
|
||||
class="group relative"
|
||||
x-show="searchQuery === '' || '<%= content_item.name.downcase %>'.includes(searchQuery.toLowerCase()) || '<%= content_item.respond_to?(:page_type) ? content_item.page_type.downcase : content_item.class.name.downcase %>'.includes(searchQuery.toLowerCase())"
|
||||
x-data="{
|
||||
isFavorite: <%= content_item.respond_to?(:favorite?) ? content_item.favorite? : false %>,
|
||||
isLoading: false,
|
||||
async toggleFavorite(event) {
|
||||
if (!this.canFavorite) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const result = await window.toggleItemFavorite('<%= content_item.id %>', '<%= content_item.respond_to?(:page_type) ? content_item.page_type.downcase.pluralize : content_item.class.name.downcase.pluralize %>');
|
||||
if (result.success) {
|
||||
this.isFavorite = !this.isFavorite;
|
||||
} else {
|
||||
alert('Error toggling favorite. Please try again.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
alert('An unexpected error occurred. Please check the console.');
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
canFavorite: <%= content_item.respond_to?(:favorite?) ? 'true' : 'false' %>
|
||||
}"
|
||||
>
|
||||
<%= link_to (content_item.respond_to?(:view_path) ? content_item.view_path : content_item), class: "block" do %>
|
||||
<div class="bg-white hover:shadow-xl rounded-lg transition-shadow duration-200 overflow-hidden">
|
||||
@ -389,6 +530,17 @@
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if content_item.respond_to?(:favorite?) %>
|
||||
<button
|
||||
@click="toggleFavorite"
|
||||
:disabled="isLoading"
|
||||
class="absolute top-4 right-4 group p-1 text-xl rounded-lg bg-white/80 backdrop-blur-sm hover:bg-notebook-blue hover:shadow-md focus:outline-none focus:ring-2 focus:ring-yellow-500 transition-all"
|
||||
:class="{ 'opacity-50 cursor-not-allowed': isLoading }"
|
||||
title="Toggle favorite"
|
||||
>
|
||||
<i class="material-icons" :class="isFavorite ? 'text-yellow-400' : 'text-gray-400 group-hover:text-yellow-400'" x-text="isFavorite ? 'star' : 'star_outline'"></i>
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
@ -397,8 +549,32 @@
|
||||
<div x-show="viewMode === 'list'" style="display: none;" class="bg-white rounded-lg border border-gray-200 overflow-hidden">
|
||||
<% @content.each_with_index do |content_item, index| %>
|
||||
<div
|
||||
class="<%= 'border-t border-gray-200' if index > 0 %> hover:bg-gray-50 transition-colors"
|
||||
class="<%= 'border-t border-gray-200' if index > 0 %> hover:bg-gray-50 transition-colors relative"
|
||||
x-show="searchQuery === '' || '<%= content_item.name.downcase %>'.includes(searchQuery.toLowerCase()) || '<%= content_item.respond_to?(:page_type) ? content_item.page_type.downcase : content_item.class.name.downcase %>'.includes(searchQuery.toLowerCase())"
|
||||
x-data="{
|
||||
isFavorite: <%= content_item.respond_to?(:favorite?) ? content_item.favorite? : false %>,
|
||||
isLoading: false,
|
||||
async toggleFavorite(event) {
|
||||
if (!this.canFavorite) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const result = await window.toggleItemFavorite('<%= content_item.id %>', '<%= content_item.respond_to?(:page_type) ? content_item.page_type.downcase.pluralize : content_item.class.name.downcase.pluralize %>');
|
||||
if (result.success) {
|
||||
this.isFavorite = !this.isFavorite;
|
||||
} else {
|
||||
alert('Error toggling favorite. Please try again.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
alert('An unexpected error occurred. Please check the console.');
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
canFavorite: <%= content_item.respond_to?(:favorite?) ? 'true' : 'false' %>
|
||||
}"
|
||||
>
|
||||
<%= link_to (content_item.respond_to?(:view_path) ? content_item.view_path : content_item), class: "flex items-center p-4 space-x-4" do %>
|
||||
<div class="flex-shrink-0">
|
||||
@ -424,21 +600,32 @@
|
||||
<i class="material-icons text-gray-400">chevron_right</i>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if content_item.respond_to?(:favorite?) %>
|
||||
<button
|
||||
@click="toggleFavorite"
|
||||
:disabled="isLoading"
|
||||
class="absolute right-12 top-1/2 transform -translate-y-1/2 p-1 text-lg rounded-full hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-yellow-500"
|
||||
:class="{ 'opacity-50 cursor-not-allowed': isLoading }"
|
||||
title="Toggle favorite"
|
||||
>
|
||||
<i class="material-icons" :class="isFavorite ? 'text-yellow-400' : 'text-gray-300 hover:text-gray-400'" x-text="isFavorite ? 'star' : 'star_outline'"></i>
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<!-- Empty State -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-8 text-center">
|
||||
<div class="mx-auto h-16 w-16 rounded-full bg-gray-100 flex items-center justify-center mb-4">
|
||||
<i class="material-icons text-2xl text-gray-400">folder_open</i>
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-8 text-center shadow-sm hover:shadow-md transition-shadow">
|
||||
<div class="mx-auto h-24 w-24 rounded-full bg-gradient-to-br from-gray-100 to-gray-200 flex items-center justify-center mb-6 shadow-sm">
|
||||
<i class="material-icons text-4xl text-gray-400">folder_open</i>
|
||||
</div>
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-2">This folder is empty</h3>
|
||||
<p class="text-gray-500 mb-4">Add content to this folder by selecting "Move to folder" when viewing any page.</p>
|
||||
<div class="flex flex-wrap justify-center gap-3">
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-3">This folder is empty</h3>
|
||||
<p class="text-gray-600 mb-6 max-w-md mx-auto">Add content to this folder by selecting "Move to folder" when viewing any page, or create new content directly.</p>
|
||||
<div class="flex flex-wrap justify-center gap-3 max-w-lg mx-auto">
|
||||
<% Rails.application.config.content_types[:free].each do |content_type| %>
|
||||
<%= link_to new_polymorphic_path(content_type) do %>
|
||||
<button class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg text-white <%= content_type.color %> hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
||||
<button class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg text-white <%= content_type.color %> hover:opacity-90 hover:shadow focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-sm transition-all duration-200">
|
||||
<i class="material-icons text-sm mr-2"><%= content_type.icon %></i>
|
||||
New <%= content_type.name %>
|
||||
</button>
|
||||
@ -458,4 +645,103 @@
|
||||
<div x-show="showEditFolderModal">
|
||||
<%= render partial: 'folders/tailwind_edit_modal', locals: { folder: @folder } %>
|
||||
</div>
|
||||
|
||||
<!-- Enhanced JavaScript -->
|
||||
<script>
|
||||
// Global function for toggling favorites
|
||||
window.toggleItemFavorite = async function(contentId, contentClass) {
|
||||
const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content');
|
||||
let postUrl = contentClass === 'documents'
|
||||
? `/documents/${contentId}/toggle_favorite`
|
||||
: `/plan/${contentClass}/${contentId}/toggle_favorite`;
|
||||
|
||||
try {
|
||||
let response = await fetch(postUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': csrfToken
|
||||
},
|
||||
body: JSON.stringify({ id: contentId })
|
||||
});
|
||||
|
||||
if (!response.ok && postUrl.startsWith('/plan/')) {
|
||||
postUrl = `/${contentClass}/${contentId}/toggle_favorite`;
|
||||
response = await fetch(postUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': csrfToken
|
||||
},
|
||||
body: JSON.stringify({ id: contentId })
|
||||
});
|
||||
}
|
||||
|
||||
return { success: response.ok };
|
||||
} catch (error) {
|
||||
console.error('Fetch error:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Keyboard shortcuts
|
||||
document.addEventListener('keydown', function(e) {
|
||||
// Only if not typing in an input field
|
||||
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
||||
|
||||
// CMD/Ctrl + K to focus search
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
const searchInput = document.querySelector('input[x-model="searchQuery"]');
|
||||
if (searchInput) {
|
||||
searchInput.focus();
|
||||
searchInput.select();
|
||||
}
|
||||
}
|
||||
|
||||
// CMD/Ctrl + \ to toggle content sidebar
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === '\\') {
|
||||
e.preventDefault();
|
||||
const toggleButton = document.querySelector('[\\@click="showContentSidebar = !showContentSidebar"]');
|
||||
if (toggleButton) toggleButton.click();
|
||||
}
|
||||
|
||||
// 1 for grid view, 2 for list view
|
||||
if (e.key === '1') {
|
||||
e.preventDefault();
|
||||
window.Alpine && window.Alpine.evaluate(document.querySelector('[x-data]'), 'viewMode = "grid"');
|
||||
}
|
||||
if (e.key === '2') {
|
||||
e.preventDefault();
|
||||
window.Alpine && window.Alpine.evaluate(document.querySelector('[x-data]'), 'viewMode = "list"');
|
||||
}
|
||||
});
|
||||
|
||||
// Search empty state management
|
||||
function updateSearchEmptyState() {
|
||||
const searchInput = document.querySelector('input[x-model="searchQuery"]');
|
||||
const searchEmptyState = document.getElementById('search-empty-state');
|
||||
|
||||
if (!searchInput || !searchEmptyState) return;
|
||||
|
||||
const searchQuery = searchInput.value.trim();
|
||||
const visibleItems = document.querySelectorAll('[x-show*="searchQuery"]:not([style*="display: none"])');
|
||||
|
||||
if (searchQuery && visibleItems.length === 0) {
|
||||
searchEmptyState.style.display = 'block';
|
||||
} else {
|
||||
searchEmptyState.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Watch for search input changes
|
||||
const searchInput = document.querySelector('input[x-model="searchQuery"]');
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', () => {
|
||||
setTimeout(updateSearchEmptyState, 100); // Small delay to let Alpine.js update visibility
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user