From 7ba2272dc2fb605fd74654de3cb649ee55011308 Mon Sep 17 00:00:00 2001 From: chu eun ju Date: Wed, 17 Dec 2025 17:10:57 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9C=A0=EC=A0=84=EC=9E=90=20DB=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=EB=B0=8F=20=ED=95=84=ED=84=B0=EA=B2=80=EC=83=89=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/gene/gene.service.ts | 1 - frontend/src/app/cow/[cowNo]/page.tsx | 285 ++++++++++++++++++++------ frontend/src/lib/api/gene.api.ts | 18 +- 3 files changed, 226 insertions(+), 78 deletions(-) diff --git a/backend/src/gene/gene.service.ts b/backend/src/gene/gene.service.ts index 9bd7ed8..6b06c9d 100644 --- a/backend/src/gene/gene.service.ts +++ b/backend/src/gene/gene.service.ts @@ -24,7 +24,6 @@ export class GeneService { cowId, delDt: IsNull(), }, - relations: ['genomeRequest'], order: { chromosome: 'ASC', position: 'ASC', diff --git a/frontend/src/app/cow/[cowNo]/page.tsx b/frontend/src/app/cow/[cowNo]/page.tsx index c75a507..1ca84d6 100644 --- a/frontend/src/app/cow/[cowNo]/page.tsx +++ b/frontend/src/app/cow/[cowNo]/page.tsx @@ -150,6 +150,8 @@ export default function CowOverviewPage() { const [cow, setCow] = useState(null) const [genomeData, setGenomeData] = useState([]) const [geneData, setGeneData] = useState([]) + const [geneDataLoaded, setGeneDataLoaded] = useState(false) // 유전자 데이터 로드 여부 + const [geneDataLoading, setGeneDataLoading] = useState(false) // 유전자 데이터 로딩 중 const [loading, setLoading] = useState(true) const [activeTab, setActiveTab] = useState('genome') @@ -193,6 +195,8 @@ export default function CowOverviewPage() { const [showFarm] = useState(true) const [showAllTraits] = useState(false) const [selectedTraits, setSelectedTraits] = useState([]) + const [geneCurrentPage, setGeneCurrentPage] = useState(1) + const GENES_PER_PAGE = 50 // 농가/보은군 비교 하이라이트 모드 const [highlightMode, setHighlightMode] = useState<'farm' | 'region' | null>(null) @@ -215,12 +219,50 @@ export default function CowOverviewPage() { }, [filters.isActive, firstPinnedTrait, chartFilterTrait]) // 유전자 탭 필터 상태 - const [geneSearchKeyword, setGeneSearchKeyword] = useState('') + const [geneSearchInput, setGeneSearchInput] = useState('') // 실시간 입력값 + const [geneSearchKeyword, setGeneSearchKeyword] = useState('') // 디바운스된 검색값 const [geneTypeFilter, setGeneTypeFilter] = useState<'all' | 'QTY' | 'QLT'>('all') + + // 검색어 디바운스 (300ms) 실시간 필터링 너무 느림 + // 타이핑이 멈추고 0.3초 후에 검색이 실행 + useEffect(() => { + const timer = setTimeout(() => { + setGeneSearchKeyword(geneSearchInput) + setGeneCurrentPage(1) + }, 300) + return () => clearTimeout(timer) + }, [geneSearchInput]) const [genotypeFilter, setGenotypeFilter] = useState<'all' | 'homozygous' | 'heterozygous'>('all') - const [geneSortBy, setGeneSortBy] = useState<'snpName' | 'chromosome' | 'position' | 'genotype'>('snpName') + const [geneSortBy, setGeneSortBy] = useState<'snpName' | 'chromosome' | 'position' | 'snpType' | 'allele1' | 'allele2' | 'remarks'>('snpName') const [geneSortOrder, setGeneSortOrder] = useState<'asc' | 'desc'>('asc') + // 유전자 데이터 지연 로드 함수 + const loadGeneData = async () => { + if (geneDataLoaded || geneDataLoading) return // 이미 로드했거나 로딩 중이면 스킵 + + setGeneDataLoading(true) + try { + const geneDataResult = await geneApi.findByCowId(cowNo) + const geneList = geneDataResult || [] + setGeneData(geneList) + setGeneDataLoaded(true) + } catch (geneErr) { + console.error('유전자 데이터 조회 실패:', geneErr) + setGeneData([]) + setGeneDataLoaded(true) + } finally { + setGeneDataLoading(false) + } + } + + // 탭 변경 핸들러 + const handleTabChange = (value: string) => { + setActiveTab(value) + if (value === 'gene' && !geneDataLoaded) { + loadGeneData() + } + } + // 농가/보은군 배지 클릭 시 차트로 스크롤 + 하이라이트 const handleComparisonClick = (mode: 'farm' | 'region') => { // 토글: 같은 모드 클릭 시 해제 @@ -273,19 +315,8 @@ export default function CowOverviewPage() { setGenomeRequest(null) } - // 유전자(SNP) 데이터 가져오기 - try { - const geneDataResult = await geneApi.findByCowId(cowNo) - const geneList = geneDataResult || [] - setGeneData(geneList) - // 데이터 없어도 UI는 보여줌 - setHasGeneData(true) - } catch (geneErr) { - console.error('유전자 데이터 조회 실패:', geneErr) - setGeneData([]) - // 데이터 없어도 UI는 보여줌 - setHasGeneData(true) - } + // 유전자(SNP) 데이터는 탭 클릭 시 로드 (지연 로딩) + setHasGeneData(true) // 탭은 보여주되, 데이터는 나중에 로드 // 번식능력 데이터 (현재는 목업 - 추후 API 연동) // TODO: 번식능력 API 연동 @@ -512,7 +543,7 @@ export default function CowOverviewPage() { {/* 탭 네비게이션 */} - + - {hasGeneData ? ( + {geneDataLoading ? ( +
+
+
+

데이터를 불러오는 중...

+
+
+ ) : hasGeneData ? ( <> {/* 개체 정보 섹션 (유전체 탭과 동일) */}

개체 정보

@@ -1422,10 +1460,10 @@ export default function CowOverviewPage() {
setGeneSearchKeyword(e.target.value)} + value={geneSearchInput} + onChange={(e) => setGeneSearchInput(e.target.value)} />
@@ -1469,23 +1507,26 @@ export default function CowOverviewPage() {