diff --git a/src/app/api/suitable/list/route.ts b/src/app/api/suitable/list/route.ts
index 32eac33..edc5579 100644
--- a/src/app/api/suitable/list/route.ts
+++ b/src/app/api/suitable/list/route.ts
@@ -1,82 +1,75 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/libs/prisma'
-import { SUITABLE_HEAD_CODE, type SuitableMain } from '@/types/Suitable'
+import { type Suitable } from '@/types/Suitable'
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams
+
+ const pageNumber = parseInt(searchParams.get('pageNumber') || '0')
+ const itemPerPage = parseInt(searchParams.get('itemPerPage') || '0')
+ if (pageNumber === 0 || itemPerPage === 0) {
+ return NextResponse.json({ error: '페이지 번호와 페이지당 아이템 수가 필요합니다' }, { status: 400 })
+ }
+
+ const ids = searchParams.get('ids')
const category = searchParams.get('category')
const keyword = searchParams.get('keyword')
- let MainWhereCondition: any = {}
- const whereCondition: string[] = []
- const params: string[] = []
+ let query = `
+ SELECT
+ msm.id
+ , msm.product_name
+ , msm.manu_ft_cd
+ , msm.roof_mt_cd
+ , msm.roof_sh_cd
+ , details.detail
+ FROM ms_suitable_main msm
+ LEFT JOIN (
+ SELECT
+ msd.main_id
+ , (
+ SELECT
+ msd_json.id
+ , msd_json.trestle_mfpc_cd
+ , msd_json.trestle_manufacturer_product_name
+ , msd_json.memo
+ FROM ms_suitable_detail msd_json
+ WHERE msd.main_id = msd_json.main_id
+ FOR JSON PATH
+ ) AS detail
+ FROM ms_suitable_detail msd
+ GROUP BY msd.main_id
+ ) AS details
+ ON msm.id = details.main_id
+ --mainIds AND details.main_id IN (:mainIds)
+ WHERE 1=1
+ --mainIds AND msm.id IN (:mainIds)
+ --roofMtCd AND msm.roof_mt_cd = ':roofMtCd'
+ --productName AND msm.product_name LIKE '%:productName%'
+ ORDER BY msm.product_name
+ OFFSET (@P1 - 1) * @P2 ROWS
+ FETCH NEXT @P2 ROWS ONLY;
+ `
+
+ // 검색 조건 설정
+ if (ids) {
+ query = query.replaceAll('--mainIds ', '')
+ query = query.replaceAll(':mainIds', ids)
+ }
if (category) {
- whereCondition.push(`${SUITABLE_HEAD_CODE.ROOF_MT_CD} = @P1`)
- params.push(category)
- MainWhereCondition[SUITABLE_HEAD_CODE.ROOF_MT_CD] = category
+ query = query.replace('--roofMtCd ', '')
+ query = query.replace(':roofMtCd', category)
}
if (keyword) {
- whereCondition.push('PRODUCT_NAME LIKE @P2')
- params.push(`%${keyword}%`)
- MainWhereCondition['PRODUCT_NAME'] = {
- contains: keyword,
- }
+ query = query.replace('--productName ', '')
+ query = query.replace(':productName', keyword)
}
- const startTime = performance.now()
- console.log(`쿼리 (main table) 시작 시간: ${startTime}ms`)
// @ts-ignore
- const suitable = await prisma.MS_SUITABLE_MAIN.findMany({
- select: {
- ID: true,
- PRODUCT_NAME: true,
- ROOF_MT_CD: true,
- },
- where: MainWhereCondition,
- orderBy: {
- PRODUCT_NAME: 'asc',
- },
- })
+ const suitable: Suitable[] = await prisma.$queryRawUnsafe(query, pageNumber, itemPerPage)
- const endTime = performance.now()
- console.log(`쿼리 (main table) 종료 시간: ${endTime - startTime}ms`)
-
- const mainIds: number[] = suitable.map((item: SuitableMain) => item.id)
-
-
- const startTime2 = performance.now()
- console.log(`쿼리 (detail table) 시작 시간: ${startTime2}ms`)
- let detailQuery = `
- SELECT
- msd.main_id
- , (
- SELECT
- msd_json.id
- , msd_json.trestle_mfpc_cd
- , msd_json.trestle_manufacturer_product_name
- , msd_json.memo
- FROM ms_suitable_detail msd_json
- WHERE msd.main_id = msd_json.main_id
- FOR JSON PATH
- ) AS detail
- FROM ms_suitable_detail msd
- -- WHERE 1=1
- GROUP BY msd.main_id
- `
- if (whereCondition.length > 0) {
- detailQuery = detailQuery.replace('-- WHERE 1=1', `WHERE msd.main_id IN @P1`)
- }
- // @ts-ignore
- const detail = await prisma.$queryRawUnsafe(detailQuery, ...mainIds)
-
- const endTime2 = performance.now()
- console.log(`쿼리 (detail table) 종료 시간: ${endTime2 - startTime2}ms`)
-
- const endTime3 = performance.now()
- console.log(`쿼리 총 실행 시간: ${endTime3 - startTime}ms`)
-
- return NextResponse.json({ suitable, detail })
+ return NextResponse.json(suitable)
} catch (error) {
console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error)
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
diff --git a/src/app/api/suitable/list/test/route.ts b/src/app/api/suitable/list/test/route.ts
deleted file mode 100644
index e4688bd..0000000
--- a/src/app/api/suitable/list/test/route.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import { NextRequest, NextResponse } from 'next/server'
-import { prisma } from '@/libs/prisma'
-import { SUITABLE_HEAD_CODE, type Suitable } from '@/types/Suitable'
-
-export async function GET(request: NextRequest) {
- try {
- const searchParams = request.nextUrl.searchParams
- const category = searchParams.get('category')
- const keyword = searchParams.get('keyword')
-
- const whereCondition: string[] = []
- const params: string[] = []
- if (category) {
- whereCondition.push(`${SUITABLE_HEAD_CODE.ROOF_MT_CD} = @P1`)
- params.push(category)
- }
- if (keyword) {
- whereCondition.push('PRODUCT_NAME LIKE @P2')
- params.push(`%${keyword}%`)
- }
-
- const startTime = performance.now()
- console.log(`쿼리 시작 시간: ${startTime}ms`)
-
- let query = `
- SELECT
- msm.id
- , msm.product_name
- , msm.manu_ft_cd
- , msm.roof_mt_cd
- , msm.roof_sh_cd
- , details.detail
- FROM ms_suitable_main msm
- LEFT JOIN (
- SELECT
- msd.main_id
- , (
- SELECT
- msd_json.id
- , msd_json.trestle_mfpc_cd
- , msd_json.trestle_manufacturer_product_name
- , msd_json.memo
- FROM ms_suitable_detail msd_json
- WHERE msd.main_id = msd_json.main_id
- FOR JSON PATH
- ) AS detail
- FROM ms_suitable_detail msd
- GROUP BY msd.main_id
- ) AS details
- ON msm.id = details.main_id
- -- AND details.main_id IN (#mainIds)
- -- WHERE 1=1
- ORDER BY msm.product_name`
-
- // 검색 조건 추가
- if (whereCondition.length > 0) {
- query = query.replace('-- WHERE 1=1', `WHERE ${whereCondition.join(' AND ')}`)
- }
-
- // @ts-ignore
- const suitable: Suitable[] = await prisma.$queryRawUnsafe(query, ...params)
-
- const endTime = performance.now()
- console.log(`쿼리 실행 시간: ${endTime - startTime}ms`)
-
- return NextResponse.json(suitable)
- } catch (error) {
- console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error)
- return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
- }
-}
diff --git a/src/app/suitable-test/layout.tsx b/src/app/suitable-test/layout.tsx
deleted file mode 100644
index e5e7c3f..0000000
--- a/src/app/suitable-test/layout.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import type { ReactNode } from 'react'
-
-interface SuitableLayoutProps {
- children: ReactNode
-}
-
-export default function layout({ children }: SuitableLayoutProps) {
- return (
- <>
-
-
-
-
-
この適合表は参考資料として使用してください.
-
詳細やお問い合わせは1:1お問い合わせをご利用ください.
-
屋根材の選択or屋根材名を直接入力してください.
-
-
- {children}
-
-
- >
- )
-}
diff --git a/src/app/suitable-test/page.tsx b/src/app/suitable-test/page.tsx
deleted file mode 100644
index a5299fe..0000000
--- a/src/app/suitable-test/page.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import SuitableRaw from '@/components/suitable/SuitableRaw'
-
-export default function page() {
- return (
- <>
-
- >
- )
-}
diff --git a/src/components/suitable/Suitable.tsx b/src/components/suitable/Suitable.tsx
index 36a397f..15cda44 100644
--- a/src/components/suitable/Suitable.tsx
+++ b/src/components/suitable/Suitable.tsx
@@ -2,13 +2,13 @@
import Image from 'next/image'
import { useEffect, useState } from 'react'
-import SuitableList from './SuitableList'
+import SuitableListRaw from './SuitableList'
import { useSuitable } from '@/hooks/useSuitable'
import { useSuitableStore } from '@/store/useSuitableStore'
import type { CommCode } from '@/types/CommCode'
import { SUITABLE_HEAD_CODE } from '@/types/Suitable'
-export default function Suitable() {
+export default function SuitableRaw() {
const [reference, setReference] = useState(true)
const { getSuitableCommCode, refetchBySearch } = useSuitable()
@@ -110,7 +110,7 @@ export default function Suitable() {
-
+
)
diff --git a/src/components/suitable/SuitableList.tsx b/src/components/suitable/SuitableList.tsx
index 18d94e5..bbb8e03 100644
--- a/src/components/suitable/SuitableList.tsx
+++ b/src/components/suitable/SuitableList.tsx
@@ -6,7 +6,7 @@ import SuitableButton from './SuitableButton'
import SuitableNoData from './SuitableNoData'
import { useSuitable } from '@/hooks/useSuitable'
import { useSuitableStore } from '@/store/useSuitableStore'
-import { SUITABLE_HEAD_CODE, type SuitableMain, type SuitableDetail } from '@/types/Suitable'
+import { SUITABLE_HEAD_CODE, type Suitable, type SuitableDetail } from '@/types/Suitable'
// 한 번에 로드할 아이템 수
const ITEMS_PER_PAGE = 100
@@ -14,9 +14,8 @@ const ITEMS_PER_PAGE = 100
export default function SuitableList() {
const { toCodeName, suitableSearchResults, isSearchLoading, toSuitableDetail } = useSuitable()
const { selectedItems, addSelectedItem, removeSelectedItem } = useSuitableStore()
-
const [openItems, setOpenItems] = useState>(new Set())
- const [visibleItems, setVisibleItems] = useState([])
+ const [visibleItems, setVisibleItems] = useState([])
const [page, setPage] = useState(1)
const [isLoadingMore, setIsLoadingMore] = useState(false)
const observerTarget = useRef(null)
@@ -32,7 +31,7 @@ export default function SuitableList() {
// 초기 데이터 로드
useEffect(() => {
if (suitableSearchResults) {
- const initialItems = suitableSearchResults.suitable.slice(0, ITEMS_PER_PAGE)
+ const initialItems = suitableSearchResults.slice(0, ITEMS_PER_PAGE)
setVisibleItems(initialItems)
setPage(1)
}
@@ -46,7 +45,7 @@ export default function SuitableList() {
const nextPage = page + 1
const startIndex = (nextPage - 1) * ITEMS_PER_PAGE
const endIndex = startIndex + ITEMS_PER_PAGE
- const nextItems = suitableSearchResults.suitable.slice(startIndex, endIndex)
+ const nextItems = suitableSearchResults.slice(startIndex, endIndex)
if (nextItems.length > 0) {
setIsLoadingMore(true)
@@ -108,7 +107,7 @@ export default function SuitableList() {
// 메모이제이션된 아이템 렌더링
const renderItem = useCallback(
- (item: SuitableMain) => {
+ (item: Suitable) => {
const isSelected = isItemSelected(item.id)
const isOpen = openItems.has(item.id)
@@ -124,7 +123,7 @@ export default function SuitableList() {
- {toSuitableDetail(item.id).map((subItem: SuitableDetail) => (
+ {toSuitableDetail(item.detail).map((subItem: SuitableDetail) => (
-
@@ -158,7 +157,7 @@ export default function SuitableList() {
return
Loading...
}
- if (!suitableSearchResults?.suitable.length) {
+ if (!suitableSearchResults?.length) {
return
}
diff --git a/src/components/suitable/SuitableListRaw.tsx b/src/components/suitable/SuitableListRaw.tsx
deleted file mode 100644
index 6dc7f36..0000000
--- a/src/components/suitable/SuitableListRaw.tsx
+++ /dev/null
@@ -1,173 +0,0 @@
-'use client'
-
-import Image from 'next/image'
-import { useState, useEffect, useRef, useCallback, useMemo } from 'react'
-import SuitableButton from './SuitableButton'
-import SuitableNoData from './SuitableNoData'
-import { useSuitableRaw, type Suitable } from '@/hooks/useSuitableRaw'
-import { useSuitableStore } from '@/store/useSuitableStore'
-import { SUITABLE_HEAD_CODE, type SuitableDetail } from '@/types/Suitable'
-
-// 한 번에 로드할 아이템 수
-const ITEMS_PER_PAGE = 100
-
-export default function SuitableListRaw() {
- const { toCodeName, suitableSearchResults, isSearchLoading, toSuitableDetail } = useSuitableRaw()
- const { selectedItems, addSelectedItem, removeSelectedItem } = useSuitableStore()
- const [openItems, setOpenItems] = useState
>(new Set())
- const [visibleItems, setVisibleItems] = useState([])
- const [page, setPage] = useState(1)
- const [isLoadingMore, setIsLoadingMore] = useState(false)
- const observerTarget = useRef(null)
-
- // 선택된 아이템 확인 함수 메모이제이션
- const isItemSelected = useCallback(
- (itemId: number) => {
- return selectedItems.some((selected) => selected === itemId)
- },
- [selectedItems],
- )
-
- // 초기 데이터 로드
- useEffect(() => {
- if (suitableSearchResults) {
- const initialItems = suitableSearchResults.slice(0, ITEMS_PER_PAGE)
- setVisibleItems(initialItems)
- setPage(1)
- }
- }, [suitableSearchResults])
-
- // Intersection Observer 설정
- useEffect(() => {
- const observer = new IntersectionObserver(
- (entries) => {
- if (entries[0].isIntersecting && suitableSearchResults && !isLoadingMore) {
- const nextPage = page + 1
- const startIndex = (nextPage - 1) * ITEMS_PER_PAGE
- const endIndex = startIndex + ITEMS_PER_PAGE
- const nextItems = suitableSearchResults.slice(startIndex, endIndex)
-
- if (nextItems.length > 0) {
- setIsLoadingMore(true)
- setVisibleItems((prev) => [...prev, ...nextItems])
- setPage(nextPage)
- setIsLoadingMore(false)
- }
- }
- },
- {
- threshold: 0.2,
- },
- )
-
- if (observerTarget.current) {
- observer.observe(observerTarget.current)
- }
-
- return () => observer.disconnect()
- }, [page, suitableSearchResults, isLoadingMore])
-
- const handleItemClick = useCallback(
- (itemId: number) => {
- isItemSelected(itemId) ? removeSelectedItem(itemId) : addSelectedItem(itemId)
- },
- [isItemSelected, addSelectedItem, removeSelectedItem],
- )
-
- const toggleItemOpen = useCallback((itemId: number) => {
- setOpenItems((prev) => {
- const newOpenItems = new Set(prev)
- newOpenItems.has(itemId) ? newOpenItems.delete(itemId) : newOpenItems.add(itemId)
- return newOpenItems
- })
- }, [])
-
- // TODO: 추후 지붕재 적합성 데이터 CUD 구현 시 ×, ー 데이터 관리 필요
- const suitableCheck = useCallback((value: string) => {
- if (value === '×') {
- return (
-
-
-
- )
- } else if (value === 'ー') {
- return (
-
-
-
- )
- } else {
- return (
-
-
-
- )
- }
- }, [])
-
- // 메모이제이션된 아이템 렌더링
- const renderItem = useCallback(
- (item: Suitable) => {
- const isSelected = isItemSelected(item.id)
- const isOpen = openItems.has(item.id)
-
- return (
-
-
-
- handleItemClick(item.id)} />
-
-
-
-
-
-
-
- {toSuitableDetail(item.detail).map((subItem: SuitableDetail) => (
- -
-
-
-
-
-
-
- {suitableCheck(subItem.trestleManufacturerProductName)}
- {subItem.memo && (
-
-
-
- )}
-
-
-
- ))}
-
-
- )
- },
- [isItemSelected, openItems, handleItemClick, toggleItemOpen, suitableCheck, toCodeName, toSuitableDetail],
- )
-
- // 메모이제이션된 아이템 리스트
- const renderedItems = useMemo(() => {
- return visibleItems.map(renderItem)
- }, [visibleItems, renderItem])
-
- if (isSearchLoading) {
- return Loading...
- }
-
- if (!suitableSearchResults?.length) {
- return
- }
-
- return (
- <>
- {renderedItems}
-
- {isLoadingMore &&
데이터를 불러오는 중...
}
-
-
- >
- )
-}
diff --git a/src/components/suitable/SuitableRaw.tsx b/src/components/suitable/SuitableRaw.tsx
deleted file mode 100644
index d48dfea..0000000
--- a/src/components/suitable/SuitableRaw.tsx
+++ /dev/null
@@ -1,118 +0,0 @@
-'use client'
-
-import Image from 'next/image'
-import { useEffect, useState } from 'react'
-import SuitableListRaw from './SuitableListRaw'
-import { useSuitableRaw } from '@/hooks/useSuitableRaw'
-import { useSuitableStore } from '@/store/useSuitableStore'
-import type { CommCode } from '@/types/CommCode'
-import { SUITABLE_HEAD_CODE } from '@/types/Suitable'
-
-export default function SuitableRaw() {
- const [reference, setReference] = useState(true)
-
- const { getSuitableCommCode, refetchBySearch } = useSuitableRaw()
- const { suitableCommCode, selectedCategory, setSelectedCategory, searchValue, setSearchValue, setIsSearch, clearSelectedItems } = useSuitableStore()
-
- const handleInputSearch = async () => {
- if (!searchValue.trim()) {
- alert('屋根材の製品名を入力してください。')
- return
- }
- setIsSearch(true)
- refetchBySearch()
- }
-
- const handleInputClear = () => {
- setSearchValue('')
- setIsSearch(false)
- refetchBySearch()
- }
-
- useEffect(() => {
- refetchBySearch()
- }, [selectedCategory])
-
- useEffect(() => {
- getSuitableCommCode()
- return () => {
- setSelectedCategory('')
- setSearchValue('')
- clearSelectedItems()
- }
- }, [])
-
- return (
-
-
테스트1 페이지
-
-
-
-
-
- setSearchValue(e.target.value)}
- />
- {searchValue && }
-
-
-
-
-
-
-
凡例
-
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
-
-
-
- )
-}
diff --git a/src/hooks/useSuitable.ts b/src/hooks/useSuitable.ts
index 4bdd9b2..ece8d2e 100644
--- a/src/hooks/useSuitable.ts
+++ b/src/hooks/useSuitable.ts
@@ -2,19 +2,27 @@ import { useQuery } from '@tanstack/react-query'
import { axiosInstance, transformObjectKeys } from '@/libs/axios'
import { useSuitableStore } from '@/store/useSuitableStore'
import { useCommCode } from './useCommCode'
-import { SUITABLE_HEAD_CODE, type SuitableDetailGroup, type SuitableMain, type Suitable, type SuitableDetail } from '@/types/Suitable'
+import { SUITABLE_HEAD_CODE, type Suitable, type SuitableDetail } from '@/types/Suitable'
export function useSuitable() {
const { getCommCode } = useCommCode()
const { selectedCategory, searchValue, suitableCommCode, setSuitableCommCode, isSearch } = useSuitableStore()
- const getSuitables = async (): Promise => {
+ const getSuitables = async (): Promise => {
try {
- const response = await axiosInstance(null).get('/api/suitable/list')
+ const response = await axiosInstance(null).get('/api/suitable/list', {
+ params: {
+ pageNumber: 1,
+ itemPerPage: 1000,
+ ids: '',
+ category: '',
+ keyword: '',
+ },
+ })
return response.data
} catch (error) {
console.error('지붕재 데이터 로드 실패:', error)
- return { suitable: [], detail: [] }
+ return []
}
}
@@ -42,12 +50,8 @@ export function useSuitable() {
return commCode?.find((item) => item.code === code)?.codeJp || ''
}
- const toSuitableDetail = (mainId: number): SuitableDetail[] => {
+ const toSuitableDetail = (suitableDetailString: string): SuitableDetail[] => {
try {
- const suitableDetailString = suitableList?.detail.find((item) => item.mainId === mainId)?.detail
- if (!suitableDetailString) {
- return []
- }
const suitableDetailArray = transformObjectKeys(JSON.parse(suitableDetailString)) as SuitableDetail[]
if (!Array.isArray(suitableDetailArray)) {
throw new Error('suitableDetailArray is not an array')
@@ -59,7 +63,7 @@ export function useSuitable() {
}
}
- const { data: suitableList, isLoading: isInitialLoading } = useQuery({
+ const { data: suitableList, isLoading: isInitialLoading } = useQuery({
queryKey: ['suitables', 'list'],
queryFn: async () => await getSuitables(),
staleTime: 1000 * 60 * 10, // 10분
@@ -70,23 +74,19 @@ export function useSuitable() {
data: suitableSearchResults,
refetch: refetchBySearch,
isLoading: isSearchLoading,
- } = useQuery({
+ } = useQuery({
queryKey: ['suitables', 'search', selectedCategory, isSearch],
queryFn: async () => {
if (!isSearch && !selectedCategory) {
- // 검색 상태가 아니면 초기 데이터 반환 임시처리
- return isInitialLoading ? await getSuitables() : suitableList ?? { suitable: [], detail: [] }
+ return isInitialLoading ? await getSuitables() : suitableList ?? [] // 검색 상태가 아니면 초기 데이터 반환 임시처리
} else {
- const filteredSuitable = suitableList?.suitable.filter((item: SuitableMain) => {
- const categoryMatch = !selectedCategory || item.roofMtCd === selectedCategory
- const searchMatch = !searchValue || item.productName.includes(searchValue)
- return categoryMatch && searchMatch
- }) ?? []
- const mainIds = filteredSuitable.map((item: SuitableMain) => item.id)
- const filteredDetail = suitableList?.detail.filter((item: SuitableDetailGroup) => {
- return mainIds.includes(item.mainId)
- }) ?? []
- return { suitable: filteredSuitable, detail: filteredDetail }
+ return (
+ suitableList?.filter((item: Suitable) => {
+ const categoryMatch = !selectedCategory || item.roofMtCd === selectedCategory
+ const searchMatch = !searchValue || item.productName.includes(searchValue)
+ return categoryMatch && searchMatch
+ }) ?? []
+ )
}
},
staleTime: 1000 * 60 * 10,
diff --git a/src/hooks/useSuitableRaw.ts b/src/hooks/useSuitableRaw.ts
deleted file mode 100644
index a962244..0000000
--- a/src/hooks/useSuitableRaw.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import { useQuery } from '@tanstack/react-query'
-import { axiosInstance, transformObjectKeys } from '@/libs/axios'
-import { useSuitableStore } from '@/store/useSuitableStore'
-import { useCommCode } from './useCommCode'
-import { SUITABLE_HEAD_CODE, type SuitableDetail } from '@/types/Suitable'
-
-export type Suitable = {
- id: number
- productName: string
- manuFtCd: string
- roofMtCd: string
- roofShCd: string
- detail: string
-}
-
-export function useSuitableRaw() {
- const { getCommCode } = useCommCode()
- const { selectedCategory, searchValue, suitableCommCode, setSuitableCommCode, isSearch } = useSuitableStore()
-
- const getSuitables = async (): Promise => {
- try {
- const response = await axiosInstance(null).get('/api/suitable/list/test')
- return response.data
- } catch (error) {
- console.error('지붕재 데이터 로드 실패:', error)
- return []
- }
- }
-
- // const updateSearchResults = async (selectedCategory: string | undefined, searchValue: string | undefined): Promise => {
- // try {
- // const response = await axiosInstance(null).get('/api/suitable/list', { params: { selectedCategory, searchValue } })
- // return response.data
- // } catch (error) {
- // console.error('지붕재 데이터 검색 실패:', error)
- // return []
- // }
- // }
-
- const getSuitableCommCode = () => {
- const headCodes = Object.values(SUITABLE_HEAD_CODE) as SUITABLE_HEAD_CODE[]
- for (const code of headCodes) {
- getCommCode(code).then((res) => {
- setSuitableCommCode(code, res)
- })
- }
- }
-
- const toCodeName = (headCode: string, code: string): string => {
- const commCode = suitableCommCode.get(headCode)
- return commCode?.find((item) => item.code === code)?.codeJp || ''
- }
-
- const toSuitableDetail = (suitableDetailString: string): SuitableDetail[] => {
- try {
- const suitableDetailArray = transformObjectKeys(JSON.parse(suitableDetailString)) as SuitableDetail[]
- if (!Array.isArray(suitableDetailArray)) {
- throw new Error('suitableDetailArray is not an array')
- }
- return suitableDetailArray
- } catch (error) {
- console.error('지붕재 데이터 파싱 실패:', error)
- return []
- }
- }
-
- const { data: suitableList, isLoading: isInitialLoading } = useQuery({
- queryKey: ['suitables', 'list'],
- queryFn: async () => await getSuitables(),
- staleTime: 1000 * 60 * 10, // 10분
- gcTime: 1000 * 60 * 10, // 10분
- })
-
- const {
- data: suitableSearchResults,
- refetch: refetchBySearch,
- isLoading: isSearchLoading,
- // } = useQuery({
- } = useQuery({
- queryKey: ['suitables', 'search', selectedCategory, isSearch],
- queryFn: async () => {
- if (!isSearch && !selectedCategory) {
- return isInitialLoading ? await getSuitables() : suitableList ?? [] // 검색 상태가 아니면 초기 데이터 반환 임시처리
- } else {
- return (
- suitableList?.filter((item: Suitable) => {
- const categoryMatch = !selectedCategory || item.roofMtCd === selectedCategory
- const searchMatch = !searchValue || item.productName.includes(searchValue)
- return categoryMatch && searchMatch
- }) ?? []
- )
- }
- },
- staleTime: 1000 * 60 * 10,
- gcTime: 1000 * 60 * 10,
- enabled: true,
- })
-
- return {
- getSuitables,
- getSuitableCommCode,
- toCodeName,
- toSuitableDetail,
- suitableList,
- suitableSearchResults,
- refetchBySearch,
- isSearchLoading,
- }
-}
diff --git a/src/types/Suitable.ts b/src/types/Suitable.ts
index 2e3563b..e3966c8 100644
--- a/src/types/Suitable.ts
+++ b/src/types/Suitable.ts
@@ -25,20 +25,11 @@ export type SuitableDetail = {
memo: string
}
-// export type Suitable = {
-// id: number
-// productName: string
-// manuFtCd: string
-// roofMtCd: string
-// roofShCd: string
-// detail: string
-// }
-
-export type SuitableDetailGroup = {
- mainId: number
+export type Suitable = {
+ id: number
+ productName: string
+ manuFtCd: string
+ roofMtCd: string
+ roofShCd: string
detail: string
}
-export type Suitable = {
- suitable: SuitableMain[]
- detail: SuitableDetailGroup[]
-}
\ No newline at end of file