번식 능력 검사 리스트 및 보고서 수정

This commit is contained in:
2025-12-22 19:52:38 +09:00
parent d3dda3d929
commit 1644fcf241
15 changed files with 916 additions and 407 deletions

View File

@@ -14,7 +14,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { useGlobalFilter } from "@/contexts/GlobalFilterContext"
import { useMediaQuery } from "@/hooks/use-media-query"
import { useToast } from "@/hooks/use-toast"
import { ComparisonAveragesDto, cowApi, geneApi, GeneDetail, genomeApi, GenomeRequestDto, TraitComparisonAveragesDto } from "@/lib/api"
import { ComparisonAveragesDto, cowApi, geneApi, GeneDetail, genomeApi, GenomeRequestDto, TraitComparisonAveragesDto, mptApi } from "@/lib/api"
import { getInvalidMessage, getInvalidReason, isExcludedCow, isValidGenomeAnalysis } from "@/lib/utils/genome-analysis-config"
import { CowDetail } from "@/types/cow.types"
import { GenomeTrait } from "@/types/genome.types"
@@ -35,6 +35,7 @@ import { CategoryEvaluationCard } from "./genome/_components/category-evaluation
import { TraitComparison } from "./genome/_components/genome-integrated-comparison"
import { NormalDistributionChart } from "./genome/_components/normal-distribution-chart"
import { TraitDistributionCharts } from "./genome/_components/trait-distribution-charts"
import { MptTable } from "./reproduction/_components/mpt-table"
// 형질명 → 카테고리 매핑 (한우 35개 형질)
const TRAIT_CATEGORY_MAP: Record<string, string> = {
@@ -405,9 +406,13 @@ export default function CowOverviewPage() {
setGenomeRequest(null)
}
// 번식능력 데이터 (현재는 목업 - 추후 API 연동)
// TODO: 번식능력 API 연동
setHasReproductionData(false)
// 번식능력 데이터 조회
try {
const mptData = await mptApi.findByCowId(cowNo)
setHasReproductionData(mptData && mptData.length > 0)
} catch {
setHasReproductionData(false)
}
// 첫 번째 사용 가능한 탭 자동 선택
if (genomeExists) {
@@ -617,15 +622,19 @@ export default function CowOverviewPage() {
<ArrowLeft className="h-7 w-7 sm:h-4 sm:w-4" />
<span className="hidden sm:inline text-sm"></span>
</Button>
{/* 아이콘 */}
<div className="w-10 h-10 sm:w-14 sm:h-14 bg-primary rounded-xl flex items-center justify-center flex-shrink-0">
<BarChart3 className="h-5 w-5 sm:h-7 sm:w-7 text-primary-foreground" />
</div>
{/* 타이틀 */}
<div>
<h1 className="text-lg sm:text-3xl lg:text-4xl font-bold text-foreground"> </h1>
<p className="text-sm sm:text-lg text-muted-foreground">Analysis Report</p>
</div>
{/* 아이콘 + 타이틀 (클릭시 새로고침) */}
<button
onClick={() => window.location.reload()}
className="flex items-center gap-3 sm:gap-4 hover:opacity-80 transition-opacity cursor-pointer"
>
<div className="w-10 h-10 sm:w-14 sm:h-14 bg-primary rounded-xl flex items-center justify-center flex-shrink-0">
<BarChart3 className="h-5 w-5 sm:h-7 sm:w-7 text-primary-foreground" />
</div>
<div className="text-left">
<h1 className="text-lg sm:text-3xl lg:text-4xl font-bold text-foreground"> </h1>
<p className="text-sm sm:text-lg text-muted-foreground">Analysis Report</p>
</div>
</button>
</div>
</div>
@@ -658,6 +667,9 @@ export default function CowOverviewPage() {
>
<Activity className="hidden sm:block h-6 w-6 shrink-0" />
<span className="font-bold text-sm sm:text-xl"></span>
<span className={`text-xs sm:text-sm px-1.5 sm:px-2.5 py-0.5 sm:py-1 rounded font-semibold shrink-0 ${hasReproductionData ? 'bg-green-500 text-white' : 'bg-slate-300 text-slate-600'}`}>
{hasReproductionData ? '완료' : '미검사'}
</span>
</TabsTrigger>
</TabsList>
@@ -692,12 +704,12 @@ export default function CowOverviewPage() {
</div>
<div>
<div className="bg-muted/50 px-5 py-3 border-b border-border">
<span className="text-base font-semibold text-muted-foreground"></span>
<span className="text-base font-semibold text-muted-foreground"> ( )</span>
</div>
<div className="px-5 py-4">
<span className="text-2xl font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
{cow?.cowBirthDt && genomeData[0]?.request?.requestDt
? `${Math.floor((new Date(genomeData[0].request.requestDt).getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
</div>
@@ -730,10 +742,10 @@ export default function CowOverviewPage() {
</span>
</div>
<div className="flex items-center">
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"></span>
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"> ()</span>
<span className="flex-1 px-4 py-3.5 text-base font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
{cow?.cowBirthDt && genomeData[0]?.request?.requestDt
? `${Math.floor((new Date(genomeData[0].request.requestDt).getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
</div>
@@ -969,12 +981,12 @@ export default function CowOverviewPage() {
</div>
<div>
<div className="bg-muted/50 px-5 py-3 border-b border-border">
<span className="text-base font-semibold text-muted-foreground"></span>
<span className="text-base font-semibold text-muted-foreground"> ( )</span>
</div>
<div className="px-5 py-4">
<span className="text-2xl font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
{cow?.cowBirthDt && genomeData[0]?.request?.requestDt
? `${Math.floor((new Date(genomeData[0].request.requestDt).getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
</div>
@@ -1003,10 +1015,10 @@ export default function CowOverviewPage() {
</span>
</div>
<div className="flex items-center">
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"></span>
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"> ()</span>
<span className="flex-1 px-4 py-3.5 text-base font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
{cow?.cowBirthDt && genomeData[0]?.request?.requestDt
? `${Math.floor((new Date(genomeData[0].request.requestDt).getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
</div>
@@ -1130,12 +1142,12 @@ export default function CowOverviewPage() {
</div>
<div>
<div className="bg-muted/50 px-5 py-3 border-b border-border">
<span className="text-base font-semibold text-muted-foreground"></span>
<span className="text-base font-semibold text-muted-foreground"> ( )</span>
</div>
<div className="px-5 py-4">
<span className="text-2xl font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
{cow?.cowBirthDt && genomeData[0]?.request?.requestDt
? `${Math.floor((new Date(genomeData[0].request.requestDt).getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
</div>
@@ -1168,10 +1180,10 @@ export default function CowOverviewPage() {
</span>
</div>
<div className="flex items-center">
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"></span>
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"> ()</span>
<span className="flex-1 px-4 py-3.5 text-base font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
{cow?.cowBirthDt && genomeData[0]?.request?.requestDt
? `${Math.floor((new Date(genomeData[0].request.requestDt).getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
</div>
@@ -1666,14 +1678,10 @@ export default function CowOverviewPage() {
</div>
<div>
<div className="bg-muted/50 px-5 py-3 border-b border-border">
<span className="text-base font-semibold text-muted-foreground"></span>
<span className="text-base font-semibold text-muted-foreground"> ( )</span>
</div>
<div className="px-5 py-4">
<span className="text-2xl font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
<span className="text-2xl font-bold text-foreground">-</span>
</div>
</div>
<div>
@@ -1700,10 +1708,10 @@ export default function CowOverviewPage() {
</span>
</div>
<div className="flex items-center">
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"></span>
<span className="w-28 shrink-0 bg-muted/50 px-4 py-3.5 text-base font-medium text-muted-foreground"> ()</span>
<span className="flex-1 px-4 py-3.5 text-base font-bold text-foreground">
{cow?.cowBirthDt
? `${Math.floor((new Date().getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
{cow?.cowBirthDt && genomeData[0]?.request?.requestDt
? `${Math.floor((new Date(genomeData[0].request.requestDt).getTime() - new Date(cow.cowBirthDt).getTime()) / (1000 * 60 * 60 * 24 * 30.44))}개월`
: '-'}
</span>
</div>
@@ -1792,19 +1800,8 @@ export default function CowOverviewPage() {
{/* 번식능력 탭 */}
<TabsContent value="reproduction" className="mt-6 space-y-6">
{/* 혈액화학검사(MPT) 테이블 - 추후 사용
{/* 혈액화학검사(MPT) 테이블 */}
<MptTable cowShortNo={cowNo?.slice(-4)} cowNo={cowNo} farmNo={cow?.fkFarmNo} cow={cow} genomeRequest={genomeRequest} />
*/}
<Card className="bg-slate-50 border border-border rounded-2xl">
<CardContent className="p-8 text-center">
<Activity className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
<h3 className="text-lg font-semibold text-foreground mb-2"> </h3>
<p className="text-sm text-muted-foreground">
.
</p>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>