diff options
Diffstat (limited to 'components/pq-input/pq-input-tabs.tsx')
| -rw-r--r-- | components/pq-input/pq-input-tabs.tsx | 90 |
1 files changed, 84 insertions, 6 deletions
diff --git a/components/pq-input/pq-input-tabs.tsx b/components/pq-input/pq-input-tabs.tsx index df911d5e..6c9a1254 100644 --- a/components/pq-input/pq-input-tabs.tsx +++ b/components/pq-input/pq-input-tabs.tsx @@ -152,6 +152,7 @@ export function PQInputTabs({ projectData, isReadOnly = false, currentPQ, // 추가: 현재 PQ Submission 정보 + vendorCountry, }: { data: PQGroupData[] vendorId: number @@ -163,6 +164,7 @@ export function PQInputTabs({ status: string; type: string; } | null + vendorCountry?: string | null }) { const [isSaving, setIsSaving] = React.useState(false) @@ -208,6 +210,33 @@ export function PQInputTabs({ }) } + // 벤더 내자/외자 판별 (국가 코드 기반) + const isDomesticVendor = React.useMemo(() => { + if (!vendorCountry) return null; // null 이면 필터 미적용 + return vendorCountry === "KR" || vendorCountry === "한국"; + }, [vendorCountry]); + + // 벤더 유형에 따라 PQ 항목 필터링 + const filteredData: PQGroupData[] = React.useMemo(() => { + // 벤더 타입 정보가 없으면 전체 노출 + if (isDomesticVendor === null) return data; + + const filterItemByType = (item: any) => { + const itemType = item.type || "내외자"; + if (itemType === "내외자") return true; + if (itemType === "내자") return isDomesticVendor === true; + if (itemType === "외자") return isDomesticVendor === false; + return true; + }; + + return data + .map((group) => ({ + ...group, + items: group.items.filter(filterItemByType), + })) + .filter((group) => group.items.length > 0); + }, [data, isDomesticVendor]); + // 필터링 함수 const shouldShowItem = (isSaved: boolean) => { if (filterOptions.showAll) return true; @@ -223,7 +252,7 @@ export function PQInputTabs({ function createInitialFormValues(): PQFormValues { const answers: PQFormValues["answers"] = [] - data.forEach((group) => { + filteredData.forEach((group) => { // 그룹 내 아이템들을 코드 순서로 정렬 const sortedItems = sortByCode(group.items) @@ -383,7 +412,7 @@ export function PQInputTabs({ try { const answerData = form.getValues(`answers.${answerIndex}`) const criteriaId = answerData.criteriaId - const item = data.flatMap(group => group.items).find(item => item.criteriaId === criteriaId) + const item = filteredData.flatMap(group => group.items).find(item => item.criteriaId === criteriaId) const inputFormat = item?.inputFormat || "TEXT" // Validation // 모든 항목은 필수로 처리 (isRequired 제거됨) @@ -723,7 +752,14 @@ export function PQInputTabs({ {/* 프로젝트 정보 섹션 */} {renderProjectInfo()} - <Tabs defaultValue={data[0]?.groupName || ""} className="w-full"> + {filteredData.length === 0 ? ( + <div className="rounded-md border border-dashed p-6 text-sm text-muted-foreground"> + 표시할 PQ 항목이 없습니다. (벤더 내/외자 구분 필터 적용) + </div> + ) : ( + <> + + <Tabs defaultValue={filteredData[0]?.groupName || ""} className="w-full"> {/* Top Controls - Sticky Header */} <div className="sticky top-0 z-10 bg-background border-b border-border mb-4 pb-4"> {/* Item Count Display */} @@ -810,7 +846,7 @@ export function PQInputTabs({ <div className="flex justify-between items-center"> <TabsList className="grid grid-cols-4"> - {data.map((group) => { + {filteredData.map((group) => { const colorClasses = getTabColorClasses(group.groupName) return ( <TabsTrigger @@ -880,7 +916,7 @@ export function PQInputTabs({ </div> {/* Render each group */} - {data.map((group) => ( + {filteredData.map((group) => ( <TabsContent key={group.groupName} value={group.groupName}> {/* 2-column grid */} <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 pb-4"> @@ -958,6 +994,46 @@ export function PQInputTabs({ </CardHeader> <CardContent className="pt-3 space-y-3 h-full flex flex-col"> + {/* 기준 첨부 파일 */} + {item.criteriaAttachments && item.criteriaAttachments.length > 0 && ( + <div className="space-y-2"> + <FormLabel>기준 첨부파일</FormLabel> + <FileList> + {item.criteriaAttachments.map((file, idx) => ( + <FileListItem key={idx}> + <FileListHeader> + <FileListIcon /> + <FileListInfo> + <FileListName>{file.fileName}</FileListName> + {file.fileSize && ( + <FileListDescription>{prettyBytes(file.fileSize)}</FileListDescription> + )} + </FileListInfo> + <FileListAction + onClick={async () => { + try { + const { downloadFile } = await import('@/lib/file-download') + await downloadFile(file.filePath, file.fileName, { showToast: true }) + } catch (error) { + console.error('다운로드 오류:', error) + toast({ + title: "다운로드 실패", + description: "파일 다운로드 중 오류가 발생했습니다.", + variant: "destructive" + }) + } + }} + > + <Download className="h-4 w-4" /> + <span className="sr-only">Download</span> + </FileListAction> + </FileListHeader> + </FileListItem> + ))} + </FileList> + </div> + )} + {/* 프로젝트별 추가 필드 (contractInfo, additionalRequirement) */} {projectId && contractInfo && ( <div className="space-y-1"> @@ -1379,6 +1455,8 @@ export function PQInputTabs({ </TabsContent> ))} </Tabs> + </> + )} </form> {/* Confirmation Dialog */} @@ -1395,7 +1473,7 @@ export function PQInputTabs({ </DialogHeader> <div className="space-y-4 max-h-[600px] overflow-y-auto "> - {data.map((group, groupIndex) => ( + {filteredData.map((group, groupIndex) => ( <div key={groupIndex}> {group.items.map((item) => { const answerObj = form |
