From 722595c1319535fa02d904794a205f1d8d926ae2 Mon Sep 17 00:00:00 2001 From: Fred KISSIE Date: Thu, 19 Mar 2026 00:35:26 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20make=20site=20selector?= =?UTF-8?q?=20popover=20its=20own=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resource-target-address-item.tsx | 80 +++------------- src/components/site-selector.tsx | 91 +++++++++++++++++++ 2 files changed, 104 insertions(+), 67 deletions(-) create mode 100644 src/components/site-selector.tsx diff --git a/src/components/resource-target-address-item.tsx b/src/components/resource-target-address-item.tsx index dfefc3bf2..851b64b54 100644 --- a/src/components/resource-target-address-item.tsx +++ b/src/components/resource-target-address-item.tsx @@ -23,6 +23,7 @@ import { import { Input } from "./ui/input"; import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; import { Select, SelectContent, SelectItem, SelectTrigger } from "./ui/select"; +import { SitesSelector } from "./site-selector"; type SiteWithUpdateAvailable = ListSitesResponse["sites"][number]; @@ -54,16 +55,6 @@ export function ResourceTargetAddressItem({ }: ResourceTargetAddressItemProps) { const t = useTranslations(); - const [siteSearchQuery, setSiteSearchQuery] = useState(""); - - const { data: sites = [] } = useQuery( - orgQueries.sites({ - orgId, - query: siteSearchQuery, - perPage: 10 - }) - ); - const [selectedSite, setSelectedSite] = useState { - const allSites: Array< - Pick - > = [...sites]; - if ( - selectedSite !== null && - !( - allSites.find((site) => site.siteId)?.siteId === - selectedSite?.siteId - ) - ) { - allSites.unshift(selectedSite); - } - return allSites; - }, [sites, selectedSite]); - const handleContainerSelectForTarget = ( hostname: string, port?: number @@ -150,47 +125,18 @@ export function ResourceTargetAddressItem({ - - setSiteSearchQuery(v)} - /> - - {t("siteNotFound")} - - {sitesShown.map((site) => ( - { - updateTarget( - proxyTarget.targetId, - { - siteId: site.siteId, - siteType: site.type, - siteName: site.name - } - ); - - setSelectedSite(site); - }} - > - - {site.name} - - ))} - - - + { + updateTarget(proxyTarget.targetId, { + siteId: site.siteId, + siteType: site.type, + siteName: site.name + }); + setSelectedSite(site); + }} + /> diff --git a/src/components/site-selector.tsx b/src/components/site-selector.tsx new file mode 100644 index 000000000..9b7d44034 --- /dev/null +++ b/src/components/site-selector.tsx @@ -0,0 +1,91 @@ +import { orgQueries } from "@app/lib/queries"; +import type { ListSitesResponse } from "@server/routers/site"; +import { useQuery } from "@tanstack/react-query"; +import { useMemo, useState } from "react"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList +} from "./ui/command"; +import { cn } from "@app/lib/cn"; +import { CheckIcon } from "lucide-react"; +import { useTranslations } from "next-intl"; +import { useDebounce } from "use-debounce"; + +type Selectedsite = Pick< + ListSitesResponse["sites"][number], + "name" | "siteId" | "type" +>; + +export type SitesSelectorProps = { + orgId: string; + selectedSite?: Selectedsite | null; + onSelectSite: (selected: Selectedsite) => void; +}; + +export function SitesSelector({ + orgId, + selectedSite, + onSelectSite +}: SitesSelectorProps) { + const t = useTranslations(); + const [siteSearchQuery, setSiteSearchQuery] = useState(""); + const [debouncedQuery] = useDebounce(siteSearchQuery, 150); + + const { data: sites = [] } = useQuery( + orgQueries.sites({ + orgId, + query: debouncedQuery, + perPage: 10 + }) + ); + + // always include the selected site in the list of sites shown + const sitesShown = useMemo(() => { + const allSites: Array = [...sites]; + if ( + selectedSite && + !allSites.find((site) => site.siteId === selectedSite?.siteId) + ) { + allSites.unshift(selectedSite); + } + return allSites; + }, [sites, selectedSite]); + + return ( + + setSiteSearchQuery(v)} + /> + + {t("siteNotFound")} + + {sitesShown.map((site) => ( + { + onSelectSite(site); + }} + > + + {site.name} + + ))} + + + + ); +}