From dfdfae3018f8499240f48d28ce634f4a5c56e006 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Wed, 2 Apr 2025 09:54:08 +0000
Subject: 벤더 코멘트 처리
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/pq/project-select.tsx | 173 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 173 insertions(+)
 create mode 100644 components/pq/project-select.tsx

(limited to 'components/pq/project-select.tsx')

diff --git a/components/pq/project-select.tsx b/components/pq/project-select.tsx
new file mode 100644
index 00000000..0d6e6445
--- /dev/null
+++ b/components/pq/project-select.tsx
@@ -0,0 +1,173 @@
+"use client"
+
+import * as React from "react"
+import { Check, ChevronsUpDown, X } from "lucide-react"
+import { Button } from "@/components/ui/button"
+import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover"
+import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } from "@/components/ui/command"
+import { cn } from "@/lib/utils"
+import { getProjects, type Project } from "@/lib/rfqs/service"
+
+interface ProjectSelectorProps {
+  selectedProjectId?: number | null;
+  onProjectSelect: (project: Project | null) => void;
+  placeholder?: string;
+  showClearOption?: boolean;
+  clearOptionText?: string;
+}
+
+export function ProjectSelector({ 
+  selectedProjectId, 
+  onProjectSelect, 
+  placeholder = "프로젝트 선택...",
+  showClearOption = true,
+  clearOptionText = "일반 PQ 보기"
+}: ProjectSelectorProps) {
+  const [open, setOpen] = React.useState(false)
+  const [searchTerm, setSearchTerm] = React.useState("")
+  const [projects, setProjects] = React.useState<Project[]>([])
+  const [isLoading, setIsLoading] = React.useState(false)
+  const [selectedProject, setSelectedProject] = React.useState<Project | null>(null)
+
+  // 모든 프로젝트 데이터 로드 (한 번만)
+  React.useEffect(() => {
+    async function loadAllProjects() {
+      setIsLoading(true);
+      try {
+        const allProjects = await getProjects();
+        setProjects(allProjects);
+        
+        // 초기 선택된 프로젝트가 있으면 설정
+        if (selectedProjectId) {
+          const selected = allProjects.find(p => p.id === selectedProjectId);
+          if (selected) {
+            setSelectedProject(selected);
+          }
+        }
+      } catch (error) {
+        console.error("프로젝트 목록 로드 오류:", error);
+      } finally {
+        setIsLoading(false);
+      }
+    }
+    
+    loadAllProjects();
+  }, [selectedProjectId]);
+
+  // 클라이언트 측에서 검색어로 필터링
+  const filteredProjects = React.useMemo(() => {
+    if (!searchTerm.trim()) return projects;
+    
+    const lowerSearch = searchTerm.toLowerCase();
+    return projects.filter(
+      project => 
+        project.projectCode.toLowerCase().includes(lowerSearch) || 
+        project.projectName.toLowerCase().includes(lowerSearch)
+    );
+  }, [projects, searchTerm]);
+
+  // 프로젝트 선택 처리
+  const handleSelectProject = (project: Project) => {
+    setSelectedProject(project);
+    onProjectSelect(project);
+    setOpen(false);
+  };
+
+  // 선택 해제 처리
+  const handleClearSelection = () => {
+    setSelectedProject(null);
+    onProjectSelect(null);
+    setOpen(false);
+  };
+
+  return (
+    <div className="space-y-1">
+      {/* 선택된 프로젝트 정보 표시 (선택된 경우에만) */}
+      {selectedProject && (
+        <div className="flex items-center justify-between px-2">
+          <div className="flex flex-col">
+            <div className="text-sm font-medium">{selectedProject.projectCode}</div>
+            <div className="text-xs text-muted-foreground truncate max-w-[300px]">
+              {selectedProject.projectName}
+            </div>
+          </div>
+          <Button
+            variant="ghost"
+            size="sm"
+            className="h-7 w-7 p-0 text-muted-foreground hover:text-destructive"
+            onClick={handleClearSelection}
+          >
+            <X className="h-4 w-4" />
+            <span className="sr-only">선택 해제</span>
+          </Button>
+        </div>
+      )}
+      
+      {/* 셀렉터 컴포넌트 */}
+      <Popover open={open} onOpenChange={setOpen}>
+        <PopoverTrigger asChild>
+          <Button
+            variant="outline"
+            role="combobox"
+            aria-expanded={open}
+            className="w-full justify-between"
+          >
+            {selectedProject ? "프로젝트 변경..." : placeholder}
+            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+          </Button>
+        </PopoverTrigger>
+        
+        <PopoverContent className="w-[400px] p-0">
+          <Command>
+            <CommandInput
+              placeholder="프로젝트 코드/이름 검색..."
+              onValueChange={setSearchTerm}
+            />
+            <CommandList className="max-h-[300px]">
+              <CommandEmpty>검색 결과가 없습니다</CommandEmpty>
+              
+              {showClearOption && selectedProject && (
+                <>
+                  <CommandGroup>
+                    <CommandItem
+                      onSelect={handleClearSelection}
+                      className="text-blue-600 font-medium"
+                    >
+                      {clearOptionText}
+                    </CommandItem>
+                  </CommandGroup>
+                  <CommandSeparator />
+                </>
+              )}
+              
+              {isLoading ? (
+                <div className="py-6 text-center text-sm">로딩 중...</div>
+              ) : (
+                <CommandGroup>
+                  {filteredProjects.map((project) => (
+                    <CommandItem
+                      key={project.id}
+                      value={`${project.projectCode} ${project.projectName}`}
+                      onSelect={() => handleSelectProject(project)}
+                    >
+                      <Check
+                        className={cn(
+                          "mr-2 h-4 w-4",
+                          selectedProject?.id === project.id
+                            ? "opacity-100"
+                            : "opacity-0"
+                        )}
+                      />
+                      <span className="font-medium">{project.projectCode}</span>
+                      <span className="ml-2 text-gray-500 truncate">- {project.projectName}</span>
+                    </CommandItem>
+                  ))}
+                </CommandGroup>
+              )}
+            </CommandList>
+          </Command>
+        </PopoverContent>
+      </Popover>
+    </div>
+  );
+}
\ No newline at end of file
-- 
cgit v1.2.3

