import React, { useState, useEffect, useRef } from "react"; import { Button } from "@/components/ui/button.tsx"; import { Input } from "@/components/ui/input.tsx"; import { FormControl, FormItem, FormLabel } from "@/components/ui/form.tsx"; import { getCredentials } from "@/ui/main-axios.ts"; import { useTranslation } from "react-i18next"; import type { Credential } from "../../../../types"; interface CredentialSelectorProps { value?: number | null; onValueChange: (credentialId: number | null) => void; onCredentialSelect?: (credential: Credential | null) => void; } export function CredentialSelector({ value, onValueChange, onCredentialSelect, }: CredentialSelectorProps) { const { t } = useTranslation(); const [credentials, setCredentials] = useState([]); const [loading, setLoading] = useState(true); const [dropdownOpen, setDropdownOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(""); const buttonRef = useRef(null); const dropdownRef = useRef(null); useEffect(() => { const fetchCredentials = async () => { try { setLoading(true); const data = await getCredentials(); const credentialsArray = Array.isArray(data) ? data : data.credentials || data.data || []; setCredentials(credentialsArray); } catch { const { toast } = await import("sonner"); toast.error(t("credentials.failedToFetchCredentials")); setCredentials([]); } finally { setLoading(false); } }; fetchCredentials(); }, []); useEffect(() => { function handleClickOutside(event: MouseEvent) { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) && buttonRef.current && !buttonRef.current.contains(event.target as Node) ) { setDropdownOpen(false); } } if (dropdownOpen) { document.addEventListener("mousedown", handleClickOutside); } else { document.removeEventListener("mousedown", handleClickOutside); } return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [dropdownOpen]); const selectedCredential = credentials.find((c) => c.id === value); const filteredCredentials = credentials.filter((credential) => { if (!searchQuery) return true; const searchLower = searchQuery.toLowerCase(); return ( credential.name.toLowerCase().includes(searchLower) || credential.username.toLowerCase().includes(searchLower) || (credential.folder && credential.folder.toLowerCase().includes(searchLower)) ); }); const handleCredentialSelect = (credential: Credential) => { onValueChange(credential.id); if (onCredentialSelect) { onCredentialSelect(credential); } setDropdownOpen(false); setSearchQuery(""); }; const handleClear = () => { onValueChange(null); if (onCredentialSelect) { onCredentialSelect(null); } setDropdownOpen(false); setSearchQuery(""); }; return ( {t("hosts.selectCredential")}
{dropdownOpen && (
setSearchQuery(e.target.value)} className="h-8" />
{loading ? (
{t("common.loading")}
) : filteredCredentials.length === 0 ? (
{searchQuery ? t("credentials.noCredentialsMatchFilters") : t("credentials.noCredentialsYet")}
) : (
{value && ( )} {filteredCredentials.map((credential) => ( ))}
)}
)}
); }