From 8e70ba35379d21d89704f1095b7fd32bf286525d Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Thu, 2 Oct 2025 14:08:33 +0900
Subject: (김준회) ITB 및 일반견적 선택시 구매담당자 선택을 구매그룹코드로
 처리하도록 변경, 오라클 연결 불가한 경우 하드코딩된 폴백데이터 제공처리
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/rfq-last/table/create-general-rfq-dialog.tsx | 214 ++++++++---------------
 1 file changed, 70 insertions(+), 144 deletions(-)

(limited to 'lib/rfq-last/table/create-general-rfq-dialog.tsx')

diff --git a/lib/rfq-last/table/create-general-rfq-dialog.tsx b/lib/rfq-last/table/create-general-rfq-dialog.tsx
index 1d369648..7263f20f 100644
--- a/lib/rfq-last/table/create-general-rfq-dialog.tsx
+++ b/lib/rfq-last/table/create-general-rfq-dialog.tsx
@@ -5,8 +5,7 @@ import { useForm, useFieldArray } from "react-hook-form"
 import { zodResolver } from "@hookform/resolvers/zod"
 import { z } from "zod"
 import { format } from "date-fns"
-import { CalendarIcon, Plus, Loader2, Trash2, PlusCircle, Check, ChevronsUpDown } from "lucide-react"
-import { useRouter } from "next/navigation"
+import { CalendarIcon, Plus, Loader2, Trash2, PlusCircle } from "lucide-react"
 import { useSession } from "next-auth/react"
 
 import { Button } from "@/components/ui/button"
@@ -42,22 +41,18 @@ import {
   PopoverContent,
   PopoverTrigger,
 } from "@/components/ui/popover"
-import {
-  Command,
-  CommandInput,
-  CommandList,
-  CommandGroup,
-  CommandItem,
-  CommandEmpty,
-} from "@/components/ui/command"
 import { Calendar } from "@/components/ui/calendar"
 import { Badge } from "@/components/ui/badge"
 import { cn } from "@/lib/utils"
 import { toast } from "sonner"
 import { ScrollArea } from "@/components/ui/scroll-area"
 import { Separator } from "@/components/ui/separator"
-import { createGeneralRfqAction, getPUsersForFilter, previewGeneralRfqCode } from "../service"
+import { createGeneralRfqAction, previewGeneralRfqCode } from "../service"
 import { ProjectSelector } from "@/components/ProjectSelector"
+import { 
+  PurchaseGroupCodeSingleSelector,
+  PurchaseGroupCodeWithUser 
+} from "@/components/common/selectors/purchase-group-code"
 
 // 아이템 스키마
 const itemSchema = z.object({
@@ -90,21 +85,12 @@ interface CreateGeneralRfqDialogProps {
 export function CreateGeneralRfqDialog({ onSuccess }: CreateGeneralRfqDialogProps) {
   const [open, setOpen] = React.useState(false)
   const [isLoading, setIsLoading] = React.useState(false)
-  const [users, setUsers] = React.useState<Array<{ id: number; name: string }>>([])
-  const [isLoadingUsers, setIsLoadingUsers] = React.useState(false)
-  const [userPopoverOpen, setUserPopoverOpen] = React.useState(false)
-  const [userSearchTerm, setUserSearchTerm] = React.useState("")
+  const [selectedPurchaseGroupCode, setSelectedPurchaseGroupCode] = React.useState<PurchaseGroupCodeWithUser | undefined>(undefined)
+  const [selectorOpen, setSelectorOpen] = React.useState(false)
   const [previewCode, setPreviewCode] = React.useState("")
   const [isLoadingPreview, setIsLoadingPreview] = React.useState(false)
-  const userOptionIdsRef = React.useRef<Record<number, string>>({})
-  const router = useRouter()
   const { data: session } = useSession()
 
-  // 고유 ID 생성
-  const buttonId = React.useMemo(() => `user-button-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`, [])
-  const popoverContentId = React.useMemo(() => `user-popover-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`, [])
-  const commandId = React.useMemo(() => `user-command-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`, [])
-
   const userId = React.useMemo(() => {
     return session?.user?.id ? Number(session.user.id) : null;
   }, [session]);
@@ -171,49 +157,24 @@ export function CreateGeneralRfqDialog({ onSuccess }: CreateGeneralRfqDialogProp
     return () => subscription.unsubscribe()
   }, [form, generatePreviewCode])
 
-  // 사용자 목록 로드
-  React.useEffect(() => {
-    const loadUsers = async () => {
-      setIsLoadingUsers(true)
-      try {
-        const userList = await getPUsersForFilter()
-        setUsers(userList)
-      } catch (error) {
-        console.log("사용자 목록 로드 오류:", error)
-        toast.error("사용자 목록을 불러오는데 실패했습니다")
-      } finally {
-        setIsLoadingUsers(false)
-      }
-    }
-    loadUsers()
-  }, [])
-
-  // 세션 사용자 ID로 기본값 설정
-  React.useEffect(() => {
-    if (userId && !form.getValues("picUserId")) {
-      form.setValue("picUserId", userId)
+  // 구매그룹코드 선택 핸들러
+  const handlePurchaseGroupCodeSelect = React.useCallback((code: PurchaseGroupCodeWithUser) => {
+    setSelectedPurchaseGroupCode(code)
+    
+    // 사용자 정보가 있으면 폼에 설정
+    if (code.user) {
+      form.setValue("picUserId", code.user.id)
+    } else {
+      // 유저 정보가 없는 경우 경고
+      toast.warning(
+        `해당 구매그룹코드(${code.PURCHASE_GROUP_CODE})의 사번 정보의 유저가 없습니다`,
+        {
+          description: `사번: ${code.EMPLOYEE_NUMBER}`,
+          duration: 5000,
+        }
+      )
     }
-  }, [userId, form])
-
-  // 사용자 검색 필터링
-  const userOptions = React.useMemo(() => {
-    return users.filter((user) =>
-      user.name.toLowerCase().includes(userSearchTerm.toLowerCase())
-    )
-  }, [users, userSearchTerm])
-
-  // 선택된 사용자 찾기
-  const selectedUser = React.useMemo(() => {
-    const picUserId = form.watch("picUserId")
-    return users.find(user => user.id === picUserId)
-  }, [users, form.watch("picUserId")])
-
-  // 사용자 선택 핸들러
-  const handleSelectUser = (user: { id: number; name: string }) => {
-    form.setValue("picUserId", user.id)
-    setUserPopoverOpen(false)
-    setUserSearchTerm("")
-  }
+  }, [form])
 
   // 다이얼로그 열림/닫힘 처리 및 폼 리셋
   const handleOpenChange = (newOpen: boolean) => {
@@ -238,8 +199,7 @@ export function CreateGeneralRfqDialog({ onSuccess }: CreateGeneralRfqDialogProp
           },
         ],
       })
-      setUserSearchTerm("")
-      setUserPopoverOpen(false)
+      setSelectedPurchaseGroupCode(undefined)
       setPreviewCode("")
       setIsLoadingPreview(false)
     }
@@ -463,92 +423,47 @@ export function CreateGeneralRfqDialog({ onSuccess }: CreateGeneralRfqDialogProp
                   )}
                 />
 
-                {/* 구매 담당자 - 검색 가능한 셀렉터로 변경 */}
+                {/* 구매 담당자 - 구매그룹코드 선택기 */}
                 <FormField
                   control={form.control}
                   name="picUserId"
-                  render={({ field }) => (
+                  render={() => (
                     <FormItem className="flex flex-col">
                       <FormLabel>
-                        견적담당자 <span className="text-red-500">*</span>
+                        견적담당자 (구매그룹코드) <span className="text-red-500">*</span>
                       </FormLabel>
                       <FormControl>
-                        <Popover open={userPopoverOpen} onOpenChange={setUserPopoverOpen}>
-                          <PopoverTrigger asChild>
-                            <Button
-                              key={buttonId}
-                              type="button"
-                              variant="outline"
-                              className="w-full justify-between relative h-9"
-                              disabled={isLoadingUsers}
-                            >
-                              {isLoadingUsers ? (
-                                <>
-                                  <span>담당자 로딩 중...</span>
-                                  <Loader2 className="ml-2 h-4 w-4 animate-spin" />
-                                </>
-                              ) : (
-                                <>
-                                  <span className="truncate mr-1 flex-grow text-left">
-                                    {selectedUser ? selectedUser.name : "견적담당자를 선택하세요"}
-                                  </span>
-                                  <ChevronsUpDown className="h-4 w-4 opacity-50 flex-shrink-0" />
-                                </>
+                        <Button
+                          type="button"
+                          variant="outline"
+                          className="w-full justify-start h-auto min-h-[36px]"
+                          onClick={() => setSelectorOpen(true)}
+                        >
+                          {selectedPurchaseGroupCode ? (
+                            <div className="flex flex-col items-start gap-1 w-full">
+                              <div className="flex items-center gap-2">
+                                <Badge variant="secondary" className="font-mono text-xs">
+                                  {selectedPurchaseGroupCode.PURCHASE_GROUP_CODE}
+                                </Badge>
+                                <span className="text-sm">{selectedPurchaseGroupCode.DISPLAY_NAME}</span>
+                              </div>
+                              {selectedPurchaseGroupCode.user && (
+                                <div className="text-xs text-muted-foreground">
+                                  담당자: {selectedPurchaseGroupCode.user.name} ({selectedPurchaseGroupCode.user.email})
+                                </div>
                               )}
-                            </Button>
-                          </PopoverTrigger>
-                          <PopoverContent key={popoverContentId} className="w-[300px] p-0">
-                            <Command key={commandId}>
-                              <CommandInput
-                                key={`${commandId}-input`}
-                                placeholder="담당자 검색..."
-                                value={userSearchTerm}
-                                onValueChange={setUserSearchTerm}
-                              />
-                              <CommandList 
-                                key={`${commandId}-list`} 
-                                className="max-h-[300px]" 
-                                onWheel={(e) => {
-                                  e.stopPropagation(); // 이벤트 전파 차단
-                                  const target = e.currentTarget;
-                                  target.scrollTop += e.deltaY; // 직접 스크롤 처리
-                                }}
-                              >
-                                <CommandEmpty key={`${commandId}-empty`}>담당자를 찾을 수 없습니다.</CommandEmpty>
-                                <CommandGroup key={`${commandId}-group`}>
-                                  {userOptions.map((user, userIndex) => {
-                                    if (!userOptionIdsRef.current[user.id]) {
-                                      userOptionIdsRef.current[user.id] =
-                                        `user-${user.id}-${Date.now()}-${Math.random()
-                                          .toString(36)
-                                          .slice(2, 9)}`
-                                    }
-                                    const optionId = userOptionIdsRef.current[user.id]
-
-                                    return (
-                                      <CommandItem
-                                        key={`${optionId}-${userIndex}`}
-                                        onSelect={() => handleSelectUser(user)}
-                                        value={user.name}
-                                        className="truncate"
-                                        title={user.name}
-                                      >
-                                        <span className="truncate">{user.name}</span>
-                                        <Check
-                                          key={`${optionId}-check`}
-                                          className={cn(
-                                            "ml-auto h-4 w-4 flex-shrink-0",
-                                            selectedUser?.id === user.id ? "opacity-100" : "opacity-0"
-                                          )}
-                                        />
-                                      </CommandItem>
-                                    )
-                                  })}
-                                </CommandGroup>
-                              </CommandList>
-                            </Command>
-                          </PopoverContent>
-                        </Popover>
+                              {!selectedPurchaseGroupCode.user && (
+                                <div className="text-xs text-orange-600">
+                                  ⚠️ 연결된 사용자가 없습니다
+                                </div>
+                              )}
+                            </div>
+                          ) : (
+                            <span className="text-muted-foreground text-sm">
+                              구매그룹코드를 선택하세요
+                            </span>
+                          )}
+                        </Button>
                       </FormControl>
                       {/* RFQ 코드 미리보기 */}
                       {previewCode && (
@@ -779,6 +694,17 @@ export function CreateGeneralRfqDialog({ onSuccess }: CreateGeneralRfqDialogProp
           </Button>
         </DialogFooter>
       </DialogContent>
+
+      {/* 구매그룹코드 선택 다이얼로그 */}
+      <PurchaseGroupCodeSingleSelector
+        open={selectorOpen}
+        onOpenChange={setSelectorOpen}
+        selectedCode={selectedPurchaseGroupCode}
+        onCodeSelect={handlePurchaseGroupCodeSelect}
+        title="견적 담당자 선택"
+        description="일반견적의 담당자를 구매그룹코드로 선택하세요"
+        showConfirmButtons={false}
+      />
     </Dialog>
   )
 }
\ No newline at end of file
-- 
cgit v1.2.3

