Files
pangolin/src/components/command-palette/useCommandPaletteSearch.ts
T
2026-07-07 21:55:15 -04:00

199 lines
5.8 KiB
TypeScript

"use client";
import { orgQueries } from "@app/lib/queries";
import { useQueries } from "@tanstack/react-query";
import { useMemo } from "react";
import { useDebounce } from "use-debounce";
const SEARCH_PER_PAGE = 5;
const MIN_QUERY_LENGTH = 2;
export type SiteSearchResult = {
id: string;
name: string;
href: string;
};
export type ResourceSearchResult = {
id: string;
name: string;
href: string;
};
export type UserSearchResult = {
id: string;
name: string;
email: string;
href: string;
};
export type ClientSearchResult = {
id: string;
name: string;
href: string;
};
export function useCommandPaletteSearch({
orgId,
query,
enabled
}: {
orgId?: string;
query: string;
enabled: boolean;
}) {
const [debouncedQuery] = useDebounce(query, 150);
const trimmedQuery = debouncedQuery.trim();
const shouldSearch =
enabled && !!orgId && trimmedQuery.length >= MIN_QUERY_LENGTH;
const [
sitesQuery,
proxyResourcesQuery,
privateResourcesQuery,
usersQuery,
clientsQuery,
userDevicesQuery
] = useQueries({
queries: [
{
...orgQueries.sites({
orgId: orgId ?? "",
query: trimmedQuery,
perPage: SEARCH_PER_PAGE
}),
enabled: shouldSearch
},
{
...orgQueries.proxyResources({
orgId: orgId ?? "",
query: trimmedQuery,
perPage: SEARCH_PER_PAGE
}),
enabled: shouldSearch
},
{
...orgQueries.privateResources({
orgId: orgId ?? "",
query: trimmedQuery,
perPage: SEARCH_PER_PAGE
}),
enabled: shouldSearch
},
{
...orgQueries.users({
orgId: orgId ?? "",
query: trimmedQuery,
perPage: SEARCH_PER_PAGE
}),
enabled: shouldSearch
},
{
...orgQueries.machineClients({
orgId: orgId ?? "",
query: trimmedQuery,
perPage: SEARCH_PER_PAGE
}),
enabled: shouldSearch
},
{
...orgQueries.userDevices({
orgId: orgId ?? "",
query: trimmedQuery,
perPage: SEARCH_PER_PAGE
}),
enabled: shouldSearch
}
]
});
const sites = useMemo((): SiteSearchResult[] => {
if (!orgId || !sitesQuery.data) return [];
return sitesQuery.data.map((site) => ({
id: `site-${site.siteId}`,
name: site.name,
href: `/${orgId}/settings/sites/${site.niceId}`
}));
}, [orgId, sitesQuery.data]);
const publicResources = useMemo((): ResourceSearchResult[] => {
if (!orgId || !proxyResourcesQuery.data) return [];
return proxyResourcesQuery.data.map((resource) => ({
id: `resource-${resource.resourceId}`,
name: resource.name,
href: `/${orgId}/settings/resources/proxy/${resource.niceId}`
}));
}, [orgId, proxyResourcesQuery.data]);
const privateResources = useMemo((): ResourceSearchResult[] => {
if (!orgId || !privateResourcesQuery.data) return [];
return privateResourcesQuery.data.map((resource) => ({
id: `site-resource-${resource.siteResourceId}`,
name: resource.name,
href: `/${orgId}/settings/resources/private/${resource.niceId}`
}));
}, [orgId, privateResourcesQuery.data]);
const users = useMemo((): UserSearchResult[] => {
if (!orgId || !usersQuery.data) return [];
return usersQuery.data.map((user) => ({
id: `user-${user.id}`,
name: user.name ?? user.email ?? user.username ?? "",
email: user.email ?? user.username ?? "",
href: `/${orgId}/settings/access/users/${user.id}`
}));
}, [orgId, usersQuery.data]);
const machineClients = useMemo((): ClientSearchResult[] => {
if (!orgId || !clientsQuery.data) return [];
return clientsQuery.data
.filter((client) => !client.userId)
.map((client) => ({
id: `client-${client.clientId}`,
name: client.name,
href: `/${orgId}/settings/clients/machine/${client.niceId}`
}));
}, [orgId, clientsQuery.data]);
const userDevices = useMemo((): ClientSearchResult[] => {
if (!orgId || !userDevicesQuery.data) return [];
return userDevicesQuery.data
.filter((client) => !client.userId)
.map((client) => ({
id: `client-${client.clientId}`,
name: client.name,
href: `/${orgId}/settings/clients/user/${client.niceId}`
}));
}, [orgId, userDevicesQuery.data]);
const isLoading =
shouldSearch &&
(sitesQuery.isFetching ||
proxyResourcesQuery.isFetching ||
privateResourcesQuery.isFetching ||
usersQuery.isFetching ||
userDevicesQuery.isFetching ||
clientsQuery.isFetching);
const hasResults =
sites.length > 0 ||
publicResources.length > 0 ||
users.length > 0 ||
privateResources.length > 0 ||
userDevices.length > 0 ||
machineClients.length > 0;
return {
debouncedQuery: trimmedQuery,
shouldSearch,
sites,
publicResources,
privateResources,
users,
machineClients,
userDevices,
isLoading,
hasResults
};
}