@asgerami/zemenay-blog
Version:
Plug-and-play blog system for Next.js - Get a fully functional blog running in minutes with zero configuration
79 lines (78 loc) • 3.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useSearch = useSearch;
const react_1 = require("react");
const supabase_1 = require("../lib/supabase");
function useSearch(options = {}) {
const { searchFields = ["title", "content"], debounceMs = 300, minSearchLength = 2, } = options;
const [allPosts, setAllPosts] = (0, react_1.useState)([]);
const [filteredPosts, setFilteredPosts] = (0, react_1.useState)([]);
const [loading, setLoading] = (0, react_1.useState)(true);
const [error, setError] = (0, react_1.useState)(null);
const [searchQuery, setSearchQuery] = (0, react_1.useState)("");
const [debouncedQuery, setDebouncedQuery] = (0, react_1.useState)("");
// Debounce search query
(0, react_1.useEffect)(() => {
const timer = setTimeout(() => {
setDebouncedQuery(searchQuery);
}, debounceMs);
return () => clearTimeout(timer);
}, [searchQuery, debounceMs]);
// Fetch all posts once on mount
(0, react_1.useEffect)(() => {
async function fetchAllPosts() {
setLoading(true);
setError(null);
try {
const supabase = (0, supabase_1.getSupabaseClient)();
const { data, error: fetchError } = await supabase
.from("posts")
.select("*")
.order("created_at", { ascending: false });
if (fetchError)
throw fetchError;
const posts = data || [];
setAllPosts(posts);
setFilteredPosts(posts);
}
catch (err) {
setError(err instanceof Error ? err.message : "Failed to fetch posts");
setAllPosts([]);
setFilteredPosts([]);
}
finally {
setLoading(false);
}
}
fetchAllPosts();
}, []);
// Filter posts based on search query
(0, react_1.useEffect)(() => {
if (!debouncedQuery || debouncedQuery.length < minSearchLength) {
// No search or query too short - show all posts
setFilteredPosts(allPosts);
return;
}
// Filter posts locally
const query = debouncedQuery.toLowerCase();
const filtered = allPosts.filter((post) => {
const titleMatch = searchFields.includes("title") &&
post.title.toLowerCase().includes(query);
const contentMatch = searchFields.includes("content") &&
post.content.toLowerCase().includes(query);
return titleMatch || contentMatch;
});
setFilteredPosts(filtered);
}, [debouncedQuery, allPosts, searchFields, minSearchLength]);
const totalResults = filteredPosts.length;
const hasSearched = debouncedQuery.length >= minSearchLength;
return {
posts: filteredPosts,
loading,
error,
searchQuery,
setSearchQuery,
totalResults,
hasSearched,
};
}