diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/vendor-document-list/enhanced-document-service.ts | 18 | ||||
| -rw-r--r-- | lib/vendor-document-list/ship/enhanced-documents-table.tsx | 87 | ||||
| -rw-r--r-- | lib/vendor-document-list/validations.ts | 4 |
3 files changed, 58 insertions, 51 deletions
diff --git a/lib/vendor-document-list/enhanced-document-service.ts b/lib/vendor-document-list/enhanced-document-service.ts index e5cce1b1..96a5ecff 100644 --- a/lib/vendor-document-list/enhanced-document-service.ts +++ b/lib/vendor-document-list/enhanced-document-service.ts @@ -1059,12 +1059,30 @@ export async function getDocumentDetails(documentId: number) { ilike(simplifiedDocumentsView.vendorDocNumber, searchTerm), ) } + + // 4.5. B4 필터 처리 (drawingMoveGbn 기반) + let b4FilterWhere + if (input.b4FilterType && input.b4FilterType !== 'all') { + if (input.b4FilterType === 'gtt_deliverable') { + b4FilterWhere = eq(simplifiedDocumentsView.drawingMoveGbn, '도면입수') + } else if (input.b4FilterType === 'shi_input') { + b4FilterWhere = eq(simplifiedDocumentsView.drawingMoveGbn, '도면제출') + } + } + + // 4.6. Project Code 필터 처리 + let projectCodeWhere + if (input.projectCode && input.projectCode !== 'all') { + projectCodeWhere = eq(simplifiedDocumentsView.projectCode, input.projectCode) + } // 5. 최종 WHERE 조건 (계약 ID들로 필터링) const finalWhere = and( eq(simplifiedDocumentsView.vendorId, Number(companyId)), advancedWhere, globalWhere, + b4FilterWhere, + projectCodeWhere, ) // 6. 정렬 처리 diff --git a/lib/vendor-document-list/ship/enhanced-documents-table.tsx b/lib/vendor-document-list/ship/enhanced-documents-table.tsx index dabb05bb..663caeeb 100644 --- a/lib/vendor-document-list/ship/enhanced-documents-table.tsx +++ b/lib/vendor-document-list/ship/enhanced-documents-table.tsx @@ -18,6 +18,7 @@ import { DataTable } from "@/components/data-table/data-table" import { SimplifiedDocumentsView } from "@/db/schema" import { getSimplifiedDocumentColumns } from "./enhanced-doc-table-columns" import { EnhancedDocTableToolbarActions } from "./enhanced-doc-table-toolbar-actions" +import { useQueryStates, parseAsString, parseAsStringEnum, parseAsInteger } from "nuqs" // 🔥 Project Code 필터를 위한 Select 컴포넌트 import 추가 import { @@ -70,19 +71,31 @@ export function SimplifiedDocumentsTable({ const { data, pageCount, drawingKind } = documentData const { primaryDrawingKind, b4Stats: serverB4Stats } = statsData - // 🔥 B4 필터 상태 추가 - const [b4FilterType, setB4FilterType] = React.useState<'all' | 'gtt_deliverable' | 'shi_input'>('all') - - // 🔥 Project Code 필터 상태 추가 - const [selectedProjectCode, setSelectedProjectCode] = React.useState<string>('all') + // 🔥 URL searchParams를 통한 필터 상태 관리 + const [{ b4FilterType, projectCode, page }, setQueryStates] = useQueryStates( + { + b4FilterType: parseAsStringEnum<'all' | 'gtt_deliverable' | 'shi_input'>(['all', 'gtt_deliverable', 'shi_input']).withDefault('all'), + projectCode: parseAsString.withDefault('all'), + page: parseAsInteger.withDefault(1), + }, + { + history: "push", + shallow: false, + } + ) + + // page 변수는 현재 사용하지 않지만, setQueryStates에서 page를 업데이트하기 위해 필요 + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const _ensurePageIsInState = page - // 🔥 고유한 Project Code 목록 추출 및 카운트 메모이제이션 + // 🔥 통계 데이터를 위한 전체 데이터 조회 (필터링 없이) const projectCodeStats = React.useMemo(() => { + // statsData에서 전체 프로젝트 코드 목록을 가져옴 (향후 개선 가능) const projectMap = new Map<string, number>() data.forEach(doc => { - const projectCode = doc.projectCode || 'Unknown' - projectMap.set(projectCode, (projectMap.get(projectCode) || 0) + 1) + const code = doc.projectCode || 'Unknown' + projectMap.set(code, (projectMap.get(code) || 0) + 1) }) // 정렬된 배열로 변환 (프로젝트 코드 알파벳순) @@ -91,40 +104,12 @@ export function SimplifiedDocumentsTable({ .map(([code, count]) => ({ code, count })) }, [data]) - // 🔥 데이터 로드 콜백을 useCallback으로 최적화 - const handleDataLoaded = React.useCallback((loadedData: SimplifiedDocumentsView[]) => { - onDataLoaded?.(loadedData) - }, [onDataLoaded]) - - // 🔥 B4 및 Project Code 필터링된 데이터 메모이제이션 - const filteredData = React.useMemo(() => { - let result: SimplifiedDocumentsView[] = data - - // B4 필터 적용 - if (b4FilterType !== 'all') { - if (b4FilterType === 'gtt_deliverable') { - result = result.filter(doc => doc.drawingMoveGbn === '도면입수') - } else if (b4FilterType === 'shi_input') { - result = result.filter(doc => doc.drawingMoveGbn === '도면제출') - } - } - - // Project Code 필터 적용 - if (selectedProjectCode !== 'all') { - result = result.filter(doc => - (doc.projectCode || 'Unknown') === selectedProjectCode - ) - } - - return result - }, [data, b4FilterType, selectedProjectCode]) - - // 🔥 데이터가 로드되면 콜백 호출 (필터링된 데이터 사용) + // 🔥 데이터 로드 콜백 (서버에서 이미 필터링되어 옴) React.useEffect(() => { - if (filteredData && handleDataLoaded) { - handleDataLoaded(filteredData) + if (data && onDataLoaded) { + onDataLoaded(data) } - }, [filteredData, handleDataLoaded]) + }, [data, onDataLoaded]) // 🔥 컬럼 메모이제이션 최적화 const columns = React.useMemo( @@ -268,7 +253,7 @@ export function SimplifiedDocumentsTable({ // 🔥 B4 문서 존재 여부 체크 메모이제이션 const hasB4Documents = React.useMemo(() => { - return data.some(doc => doc.drawingKind === 'B4') + return data.some((doc: SimplifiedDocumentsView) => doc.drawingKind === 'B4') }, [data]) // 🔥 최종 필터 필드 메모이제이션 @@ -286,7 +271,7 @@ export function SimplifiedDocumentsTable({ const getRowId = React.useCallback((originalRow: SimplifiedDocumentsView) => String(originalRow.documentId), []) const { table } = useDataTable({ - data: filteredData, + data, // 서버에서 이미 필터링된 데이터 사용 columns, pageCount, enablePinning: true, @@ -324,7 +309,7 @@ export function SimplifiedDocumentsTable({ </div> <div className="flex items-center gap-2"> <Badge variant="outline"> - {filteredData.length} documents + {data.length} documents </Badge> </div> </div> @@ -339,8 +324,8 @@ export function SimplifiedDocumentsTable({ <Label className="text-sm font-medium">Project:</Label> </div> <Select - value={selectedProjectCode} - onValueChange={setSelectedProjectCode} + value={projectCode} + onValueChange={(value) => setQueryStates({ projectCode: value, page: 1 })} > <SelectTrigger className="w-[200px]"> <SelectValue placeholder="Select a project" /> @@ -367,11 +352,11 @@ export function SimplifiedDocumentsTable({ </SelectContent> </Select> - {selectedProjectCode !== 'all' && ( + {projectCode !== 'all' && ( <Button variant="ghost" size="sm" - onClick={() => setSelectedProjectCode('all')} + onClick={() => setQueryStates({ projectCode: 'all', page: 1 })} className="h-8" > Clear filter @@ -379,7 +364,7 @@ export function SimplifiedDocumentsTable({ )} </div> - {/* B4 필터 버튼 - 기존 코드 유지 */} + {/* B4 필터 버튼 - URL searchParams 업데이트로 변경 */} {hasB4Documents && b4Stats && ( <div className="flex items-center gap-2 p-4 bg-muted/50 rounded-lg"> <Label className="text-sm font-medium">Document Type:</Label> @@ -387,7 +372,7 @@ export function SimplifiedDocumentsTable({ <Button variant={b4FilterType === 'all' ? 'default' : 'outline'} size="sm" - onClick={() => setB4FilterType('all')} + onClick={() => setQueryStates({ b4FilterType: 'all', page: 1 })} className="gap-2" > <FileText className="h-4 w-4" /> @@ -399,7 +384,7 @@ export function SimplifiedDocumentsTable({ <Button variant={b4FilterType === 'gtt_deliverable' ? 'default' : 'outline'} size="sm" - onClick={() => setB4FilterType('gtt_deliverable')} + onClick={() => setQueryStates({ b4FilterType: 'gtt_deliverable', page: 1 })} className="gap-2" > <FileInput className="h-4 w-4" /> @@ -411,7 +396,7 @@ export function SimplifiedDocumentsTable({ <Button variant={b4FilterType === 'shi_input' ? 'default' : 'outline'} size="sm" - onClick={() => setB4FilterType('shi_input')} + onClick={() => setQueryStates({ b4FilterType: 'shi_input', page: 1 })} className="gap-2" > <FileOutput className="h-4 w-4" /> diff --git a/lib/vendor-document-list/validations.ts b/lib/vendor-document-list/validations.ts index 88e68d67..91dbdaf2 100644 --- a/lib/vendor-document-list/validations.ts +++ b/lib/vendor-document-list/validations.ts @@ -48,6 +48,10 @@ export const searchParamsShipDocuCache = createSearchParamsCache({ joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), search: parseAsString.withDefault(""), + // B4 filter and project code filter + b4FilterType: parseAsStringEnum(["all", "gtt_deliverable", "shi_input"]).withDefault("all"), + projectCode: parseAsString.withDefault("all"), + }) |
