Scrapboard.org client
at main 120 lines 3.3 kB view raw
1"use client"; 2 3import * as React from "react"; 4import { CheckIcon, ChevronsUpDownIcon, PlusIcon } from "lucide-react"; 5 6import { cn } from "@/lib/utils"; 7import { Button } from "@/components/ui/button"; 8import { 9 Command, 10 CommandEmpty, 11 CommandGroup, 12 CommandInput, 13 CommandItem, 14 CommandList, 15} from "@/components/ui/command"; 16import { 17 Popover, 18 PopoverContent, 19 PopoverTrigger, 20} from "@/components/ui/popover"; 21import { Board } from "@/lib/stores/boards"; 22import clsx from "clsx"; 23import { useAuth } from "@/lib/hooks/useAuth"; 24 25export function BoardsPicker({ 26 boards, 27 onCreateBoard, 28 onSelected: setValue, 29 selected: value, 30}: { 31 selected: string; 32 onSelected: (value: string) => unknown; 33 boards: Record< 34 string, 35 Record< 36 string, 37 { 38 name: string; 39 description: string; 40 } 41 > 42 >; 43 onCreateBoard: (name: string) => void; // New prop 44}) { 45 const [open, setOpen] = React.useState(false); 46 const [search, setSearch] = React.useState(""); 47 const { agent } = useAuth(); 48 49 if (!agent) return <div>Not logged in :(</div>; 50 51 const entries = Array.from(Object.entries(boards[agent?.assertDid])).filter( 52 ([_, board]) => board.name.toLowerCase().includes(search.toLowerCase()) 53 ); 54 55 const selectedBoard = boards[agent?.assertDid]?.[value]; 56 57 return ( 58 <Popover open={open} onOpenChange={setOpen}> 59 <PopoverTrigger asChild> 60 <Button 61 variant="outline" 62 role="combobox" 63 aria-expanded={open} 64 className={clsx( 65 "w-full justify-between", 66 selectedBoard ? "dark:text-white text-black" : "" 67 )} 68 > 69 {selectedBoard ? selectedBoard.name : "Select board..."} 70 <ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" /> 71 </Button> 72 </PopoverTrigger> 73 <PopoverContent className="w-full p-0"> 74 <Command shouldFilter={false}> 75 <CommandInput 76 placeholder="Search or create a board..." 77 onValueChange={(val) => setSearch(val)} 78 /> 79 <CommandList> 80 <CommandGroup> 81 {entries.length > 0 ? ( 82 entries.map(([key, it]) => ( 83 <CommandItem 84 key={key} 85 value={it.name} 86 onSelect={() => { 87 setValue(key === value ? "" : key); 88 setOpen(false); 89 }} 90 > 91 <CheckIcon 92 className={cn( 93 "mr-2 h-4 w-4", 94 value === key ? "opacity-100" : "opacity-0" 95 )} 96 /> 97 {it.name} 98 </CommandItem> 99 )) 100 ) : ( 101 <CommandItem 102 onSelect={() => { 103 onCreateBoard(search.trim()); 104 setSearch(""); 105 setOpen(false); 106 }} 107 > 108 <PlusIcon className="h-4 w-4" /> 109 <span> 110 Create board: <b>{search.trim()}</b> 111 </span> 112 </CommandItem> 113 )} 114 </CommandGroup> 115 </CommandList> 116 </Command> 117 </PopoverContent> 118 </Popover> 119 ); 120}