52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { findSimilarSR } from '../services/api'
|
|
|
|
export interface DuplicateTask {
|
|
id: number
|
|
sr_id?: string
|
|
title: string
|
|
status?: string
|
|
similarity?: number
|
|
}
|
|
|
|
/**
|
|
* 기능 #9 — 중복 SR 감지 훅
|
|
* 제목 입력 시 500ms debounce 후 유사 SR 조회.
|
|
* 유사도 70% 이상(또는 서버가 반환한 항목)을 경고로 노출.
|
|
*/
|
|
export function useDuplicateSR(title: string) {
|
|
const [duplicates, setDuplicates] = useState<DuplicateTask[]>([])
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
useEffect(() => {
|
|
const trimmed = title.trim()
|
|
if (trimmed.length < 4) {
|
|
setDuplicates([])
|
|
setLoading(false)
|
|
return
|
|
}
|
|
|
|
let alive = true
|
|
setLoading(true)
|
|
const timer = setTimeout(async () => {
|
|
try {
|
|
const res = await findSimilarSR(trimmed, 3)
|
|
const list: DuplicateTask[] = res.data?.content ?? res.data?.items ?? res.data ?? []
|
|
// 서버가 similarity 점수를 주면 70% 이상만, 아니면 반환 항목 그대로
|
|
const filtered = list.filter(d =>
|
|
d.similarity === undefined || d.similarity >= 0.7
|
|
)
|
|
if (alive) setDuplicates(filtered.slice(0, 3))
|
|
} catch {
|
|
if (alive) setDuplicates([])
|
|
} finally {
|
|
if (alive) setLoading(false)
|
|
}
|
|
}, 500)
|
|
|
|
return () => { alive = false; clearTimeout(timer) }
|
|
}, [title])
|
|
|
|
return { duplicates, loading, hasDuplicates: duplicates.length > 0 }
|
|
}
|