diff options
Diffstat (limited to 'components/notice/notice-create-dialog.tsx')
| -rw-r--r-- | components/notice/notice-create-dialog.tsx | 107 |
1 files changed, 79 insertions, 28 deletions
diff --git a/components/notice/notice-create-dialog.tsx b/components/notice/notice-create-dialog.tsx index 591b2bc7..98c66c99 100644 --- a/components/notice/notice-create-dialog.tsx +++ b/components/notice/notice-create-dialog.tsx @@ -7,7 +7,7 @@ import { useForm } from "react-hook-form" import { useParams } from "next/navigation"
import { useTranslation } from "@/i18n/client"
import { toast } from "sonner"
-import { Loader } from "lucide-react"
+import { Loader, Check, ChevronsUpDown } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Dialog,
@@ -25,13 +25,9 @@ import { } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Switch } from "@/components/ui/switch"
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select"
+import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
+import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from "@/components/ui/command"
+import { cn } from "@/lib/utils"
import TiptapEditor from "@/components/qna/tiptap-editor"
import { createNotice } from "@/lib/notice/service"
import { createNoticeSchema, type CreateNoticeSchema } from "@/lib/notice/validations"
@@ -135,26 +131,81 @@ export function NoticeCreateDialog({ <FormField
control={form.control}
name="pagePath"
- render={({ field }) => (
- <FormItem>
- <FormLabel>페이지 경로 *</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="페이지를 선택하세요" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {pagePathOptions.map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {safeTranslate(option.label)} - {option.value}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
+ render={({ field }) => {
+ const [open, setOpen] = useState(false)
+ const [searchTerm, setSearchTerm] = useState("")
+
+ const filteredOptions = React.useMemo(() => {
+ if (!searchTerm.trim()) return pagePathOptions
+
+ const lowerSearch = searchTerm.toLowerCase()
+ return pagePathOptions.filter(
+ (option) =>
+ safeTranslate(option.label).toLowerCase().includes(lowerSearch) ||
+ option.value.toLowerCase().includes(lowerSearch)
+ )
+ }, [pagePathOptions, searchTerm])
+
+ const selectedOption = pagePathOptions.find(option => option.value === field.value)
+
+ return (
+ <FormItem>
+ <FormLabel>페이지 경로 *</FormLabel>
+ <Popover open={open} onOpenChange={setOpen}>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ aria-expanded={open}
+ className="w-full justify-between"
+ >
+ {selectedOption
+ ? `${safeTranslate(selectedOption.label)} - ${selectedOption.value}`
+ : "페이지를 선택하세요"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-full p-0" align="start">
+ <Command>
+ <CommandInput
+ placeholder="페이지명 또는 경로 검색..."
+ onValueChange={setSearchTerm}
+ />
+ <CommandList className="max-h-[300px]">
+ <CommandEmpty>검색 결과가 없습니다</CommandEmpty>
+ <CommandGroup>
+ {filteredOptions.map((option) => (
+ <CommandItem
+ key={option.value}
+ value={`${safeTranslate(option.label)} ${option.value}`}
+ onSelect={() => {
+ field.onChange(option.value)
+ setOpen(false)
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ field.value === option.value
+ ? "opacity-100"
+ : "opacity-0"
+ )}
+ />
+ <span className="font-medium">{safeTranslate(option.label)}</span>
+ <span className="ml-2 text-gray-500 truncate">- {option.value}</span>
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
+ <FormMessage />
+ </FormItem>
+ )
+ }}
/>
<FormField
|
