import { useState } from "react"; import * as Popover from "@radix-ui/react-popover"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import * as ScrollArea from "@radix-ui/react-scroll-area"; import { Command } from "cmdk"; import { Dialogs } from "@wailsio/runtime"; import { ChevronDown, MoreVertical, PlusCircle, Search, Trash2, UserMinus } from "lucide-react"; import { cn } from "@/lib/cn"; import { generateColorFromString } from "@/lib/color"; import { NewProfileDialog } from "@/components/NewProfileDialog"; export type Profile = { id: string; name: string; }; const MOCK_PROFILES: Profile[] = [ { id: "default", name: "Default Profile" }, { id: "work", name: "Work" }, { id: "personal", name: "Personal" }, { id: "staging", name: "Staging" }, { id: "production", name: "Production" }, { id: "dev", name: "Development" }, { id: "qa", name: "QA Environment" }, { id: "demo", name: "Demo" }, { id: "client-acme", name: "Client - ACME" }, { id: "client-globex", name: "Client - Globex" }, { id: "client-initech", name: "Client - Initech" }, { id: "homelab", name: "Homelab" }, { id: "office-berlin", name: "Office Berlin" }, { id: "office-sf", name: "Office San Francisco" }, { id: "office-tokyo", name: "Office Tokyo" }, { id: "vpn-eu", name: "VPN EU" }, { id: "vpn-us", name: "VPN US" }, { id: "vpn-asia", name: "VPN Asia" }, { id: "test", name: "Test" }, { id: "sandbox", name: "Sandbox" }, ]; type Props = { email?: string; }; export const ProfileSelector = ({ email = "" }: Props) => { const [profiles, setProfiles] = useState(MOCK_PROFILES); const [selectedId, setSelectedId] = useState(MOCK_PROFILES[0].id); const [open, setOpen] = useState(false); const [newOpen, setNewOpen] = useState(false); const selected = profiles.find((p) => p.id === selectedId) ?? profiles[0]; const sorted = [...profiles].sort((a, b) => a.name.localeCompare(b.name)); const handleSelect = (id: string) => { setSelectedId(id); setOpen(false); }; const handleDeregister = async (id: string) => { const profile = profiles.find((p) => p.id === id); if (!profile) return; const result = await Dialogs.Warning({ Title: "Deregister Profile", Message: `Are you sure you want to deregister "${profile.name}"? You will need to log in again to use it.`, Buttons: [ { Label: "Cancel", IsCancel: true }, { Label: "Deregister", IsDefault: true }, ], }); if (result !== "Deregister") return; console.log("Deregister profile", id); }; const handleDelete = async (id: string) => { const profile = profiles.find((p) => p.id === id); if (!profile) return; const result = await Dialogs.Warning({ Title: "Delete Profile", Message: `Are you sure you want to delete "${profile.name}"? This action cannot be undone.`, Buttons: [ { Label: "Cancel", IsCancel: true }, { Label: "Delete", IsDefault: true }, ], }); if (result !== "Delete") return; setProfiles((prev) => prev.filter((p) => p.id !== id)); if (selectedId === id) { const remaining = profiles.filter((p) => p.id !== id); if (remaining.length > 0) setSelectedId(remaining[0].id); } }; const handleNewProfile = () => { setOpen(false); setNewOpen(true); }; const handleCreateProfile = (name: string) => { const id = `${name.toLowerCase().replace(/\s+/g, "-")}-${Date.now()}`; setProfiles((prev) => [...prev, { id, name }]); setSelectedId(id); }; const initial = selected?.name.charAt(0).toUpperCase() ?? "?"; const initialColor = generateColorFromString(selected?.name); return ( <> e.preventDefault()} >

No Profiles Found

Try a different search term or create a new profile.

{sorted.map((profile) => ( handleSelect(profile.id)} onDeregister={() => handleDeregister(profile.id)} onDelete={() => handleDelete(profile.id)} /> ))}
); }; type ProfileRowProps = { profile: Profile; selected: boolean; onSelect: () => void; onDeregister: () => void; onDelete: () => void; }; const ProfileRow = ({ profile, selected, onSelect, onDeregister, onDelete }: ProfileRowProps) => { const [menuOpen, setMenuOpen] = useState(false); const initial = profile.name.charAt(0).toUpperCase(); const initialColor = generateColorFromString(profile.name); return ( onSelect()} className={cn( "group flex items-center gap-2 pl-2 pr-3 py-1.5 rounded-md cursor-default outline-none", "data-[selected=true]:bg-nb-gray-910", selected && "bg-nb-gray-910", )} >
{initial}
{profile.name} e.stopPropagation()} onPointerDown={(e) => e.stopPropagation()} className={cn( "w-44 rounded-md border border-nb-gray-850 bg-nb-gray-910 shadow-lg p-1 z-50", )} > { e.preventDefault(); onDeregister(); setMenuOpen(false); }} className={cn( "flex items-center gap-2 px-2 py-1.5 rounded-md cursor-default outline-none font-medium", "text-xs text-nb-gray-200 data-[highlighted]:bg-nb-gray-850", )} > Deregister { e.preventDefault(); onDelete(); setMenuOpen(false); }} className={cn( "flex items-center gap-2 px-2 py-1.5 rounded-md cursor-default outline-none font-medium", "text-xs text-red-500 data-[highlighted]:bg-nb-gray-850", )} > Delete Profile
); };