summaryrefslogtreecommitdiff
path: root/lib/menu-list/table/manager-select.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/menu-list/table/manager-select.tsx')
-rw-r--r--lib/menu-list/table/manager-select.tsx192
1 files changed, 192 insertions, 0 deletions
diff --git a/lib/menu-list/table/manager-select.tsx b/lib/menu-list/table/manager-select.tsx
new file mode 100644
index 00000000..a4bcccd7
--- /dev/null
+++ b/lib/menu-list/table/manager-select.tsx
@@ -0,0 +1,192 @@
+"use client";
+
+import { useState } from "react";
+import { Check, ChevronsUpDown, Search, X } from "lucide-react";
+import { cn } from "@/lib/utils";
+import { Button } from "@/components/ui/button";
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@/components/ui/command";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+import { toast } from "sonner";
+import { updateMenuManager } from "../servcie";
+
+interface User {
+ id: number;
+ name: string;
+ email: string;
+ domain: string;
+}
+
+interface ManagerSelectProps {
+ menuPath: string;
+ currentManagerId?: number | null;
+ users: User[];
+ placeholder: string;
+ otherManagerId?: number | null; // 다른 담당자 ID (중복 선택 방지용)
+ type: "manager1" | "manager2";
+}
+
+export function ManagerSelect({
+ menuPath,
+ currentManagerId,
+ users,
+ placeholder,
+ otherManagerId,
+ type
+}: ManagerSelectProps) {
+ const [open, setOpen] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+
+ // 선택 가능한 사용자 필터링 (다른 담당자로 이미 선택된 사용자 제외)
+ const availableUsers = users.filter(user =>
+ user.id !== otherManagerId || user.id === currentManagerId
+ );
+
+ // 현재 선택된 사용자 찾기
+ const selectedUser = availableUsers.find(user => user.id === currentManagerId);
+
+ const handleSelect = async (userId: number | null) => {
+ setIsLoading(true);
+ setOpen(false);
+
+ try {
+ // 현재 담당자 정보 구성
+ const updateData = type === "manager1"
+ ? { manager1Id: userId, manager2Id: otherManagerId }
+ : { manager1Id: otherManagerId, manager2Id: userId };
+
+ const result = await updateMenuManager(
+ menuPath,
+ updateData.manager1Id,
+ updateData.manager2Id
+ );
+
+ if (result.success) {
+ toast.success(result.message);
+ } else {
+ toast.error(result.message);
+ }
+ } catch (error) {
+ toast.error("담당자 업데이트 중 오류가 발생했습니다.");
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const handleClear = () => {
+ handleSelect(null);
+ };
+
+ return (
+ <Popover open={open} onOpenChange={setOpen}>
+ <PopoverTrigger asChild>
+ <Button
+ variant="outline"
+ role="combobox"
+ aria-expanded={open}
+ className="w-full justify-between text-left font-normal"
+ disabled={isLoading}
+ >
+ {selectedUser ? (
+ <div className="flex items-center justify-between w-full">
+ <div className="flex flex-col min-w-0 flex-1">
+ <span className="font-medium truncate">{selectedUser.name}</span>
+ <span className="text-xs text-muted-foreground truncate">
+ {selectedUser.email}
+ </span>
+ </div>
+ {!isLoading && (
+ <Button
+ variant="ghost"
+ size="sm"
+ className="h-auto p-1 hover:bg-transparent"
+ onClick={(e) => {
+ e.stopPropagation();
+ handleClear();
+ }}
+ >
+ <X className="h-3 w-3" />
+ </Button>
+ )}
+ </div>
+ ) : (
+ <span className="text-muted-foreground">{placeholder}</span>
+ )}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </PopoverTrigger>
+
+ <PopoverContent className="w-[400px] p-0" align="start">
+ <Command>
+ <CommandInput
+ placeholder="사용자 검색..."
+ className="h-9"
+ />
+ <CommandList>
+ <CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
+ <CommandGroup>
+ {/* 담당자 없음 옵션 */}
+ <CommandItem
+ value="none"
+ onSelect={() => handleSelect(null)}
+ className="flex items-center gap-2"
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ !selectedUser ? "opacity-100" : "opacity-0"
+ )}
+ />
+ <div className="flex flex-col">
+ <span className="font-medium">담당자 없음</span>
+ <span className="text-xs text-muted-foreground">
+ 담당자를 지정하지 않습니다
+ </span>
+ </div>
+ </CommandItem>
+
+ {/* 사용자 목록 */}
+ {availableUsers.map((user) => (
+ <CommandItem
+ key={user.id}
+ value={`${user.name} ${user.email}`} // 검색을 위해 이름과 이메일 모두 포함
+ onSelect={() => handleSelect(user.id)}
+ className="flex items-center gap-2"
+ disabled={user.id === otherManagerId && user.id !== currentManagerId}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ selectedUser?.id === user.id ? "opacity-100" : "opacity-0"
+ )}
+ />
+ <div className="flex flex-col min-w-0 flex-1">
+ <span className="font-medium truncate">{user.name}</span>
+ <span className="text-xs text-muted-foreground truncate">
+ {user.email}
+ </span>
+ </div>
+ {user.id === otherManagerId && user.id !== currentManagerId && (
+ <span className="text-xs text-amber-600 bg-amber-50 px-1.5 py-0.5 rounded">
+ 다른 담당자로 선택됨
+ </span>
+ )}
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
+ );
+} \ No newline at end of file