Files
pangolin/src/components/resource-selector.tsx
Fred KISSIE 02697e27a4 ♻️ refactor
2026-03-20 04:02:51 +01:00

98 lines
3.2 KiB
TypeScript

import { orgQueries } from "@app/lib/queries";
import { useQuery } from "@tanstack/react-query";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList
} from "./ui/command";
import { useMemo, useState } from "react";
import { useTranslations } from "next-intl";
import { CheckIcon } from "lucide-react";
import { cn } from "@app/lib/cn";
import type { ListResourcesResponse } from "@server/routers/resource";
import { useDebounce } from "use-debounce";
export type SelectedResource = Pick<
ListResourcesResponse["resources"][number],
"name" | "resourceId" | "fullDomain" | "niceId" | "ssl"
>;
export type ResourceSelectorProps = {
orgId: string;
selectedResource?: SelectedResource | null;
onSelectResource: (resource: SelectedResource) => void;
};
export function ResourceSelector({
orgId,
selectedResource,
onSelectResource
}: ResourceSelectorProps) {
const t = useTranslations();
const [resourceSearchQuery, setResourceSearchQuery] = useState("");
const [debouncedSearchQuery] = useDebounce(resourceSearchQuery, 150);
const { data: resources = [] } = useQuery(
orgQueries.resources({
orgId: orgId,
query: debouncedSearchQuery,
perPage: 10
})
);
// always include the selected resource in the list of resources shown
const resourcesShown = useMemo(() => {
const allResources: Array<SelectedResource> = [...resources];
if (
debouncedSearchQuery.trim().length === 0 &&
selectedResource &&
!allResources.find(
(resource) =>
resource.resourceId === selectedResource?.resourceId
)
) {
allResources.unshift(selectedResource);
}
return allResources;
}, [debouncedSearchQuery, resources, selectedResource]);
return (
<Command shouldFilter={false}>
<CommandInput
placeholder={t("resourceSearch")}
value={resourceSearchQuery}
onValueChange={setResourceSearchQuery}
/>
<CommandList>
<CommandEmpty>{t("resourcesNotFound")}</CommandEmpty>
<CommandGroup>
{resourcesShown.map((r) => (
<CommandItem
value={`${r.name}:${r.resourceId}`}
key={r.resourceId}
onSelect={() => {
onSelectResource(r);
}}
>
<CheckIcon
className={cn(
"mr-2 h-4 w-4",
r.resourceId ===
selectedResource?.resourceId
? "opacity-100"
: "opacity-0"
)}
/>
{`${r.name}`}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
);
}