feat: 지붕재 적합성 데이터 아코디언 처리 추가, 적합성 아이콘 수정

This commit is contained in:
Daseul Kim 2025-05-15 14:45:20 +09:00
parent 84771ad742
commit 4392802298
3 changed files with 71 additions and 30 deletions

View File

@ -1,5 +1,6 @@
'use client' 'use client'
import Image from 'next/image'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import SuitableList from './SuitableList' import SuitableList from './SuitableList'
import { useSuitable } from '@/hooks/useSuitable' import { useSuitable } from '@/hooks/useSuitable'
@ -77,22 +78,34 @@ export default function Suitable() {
<ul className="reference-list"> <ul className="reference-list">
<li className="reference-item"> <li className="reference-item">
<div className="reference-item-bx"> <div className="reference-item-bx">
<i className="compliance-icon check"></i> <div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_check_icon.svg'} width={22} height={22} alt=""></Image>
</div>
<span></span>
</div> </div>
</li> </li>
<li className="reference-item"> <li className="reference-item">
<div className="reference-item-bx"> <div className="reference-item-bx">
<i className="compliance-icon x"></i> <div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_x_icon.svg'} width={22} height={22} alt=""></Image>
</div>
<span></span>
</div> </div>
</li> </li>
<li className="reference-item"> <li className="reference-item">
<div className="reference-item-bx"> <div className="reference-item-bx">
<i className="compliance-icon quest"></i> <div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_quest_icon.svg'} width={22} height={22} alt=""></Image>
</div>
<span></span>
</div> </div>
</li> </li>
<li className="reference-item"> <li className="reference-item">
<div className="reference-item-bx"> <div className="reference-item-bx">
<i className="compliance-icon tip"></i> <div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_tip_icon.svg'} width={22} height={22} alt=""></Image>
</div>
<span></span>
</div> </div>
</li> </li>
</ul> </ul>

View File

@ -1,71 +1,87 @@
'use client' 'use client'
import Image from 'next/image'
import { useState } from 'react'
import SuitableNoData from './SuitableNoData' import SuitableNoData from './SuitableNoData'
import { useSuitable } from '@/hooks/useSuitable' import { useSuitable } from '@/hooks/useSuitable'
import { useSuitableStore } from '@/store/useSuitableStore' import { useSuitableStore } from '@/store/useSuitableStore'
import { SUITABLE_HEAD_CODE, type SuitableMain, type SuitableDetail } from '@/types/Suitable' import { SUITABLE_HEAD_CODE, type SuitableMain, type SuitableDetail } from '@/types/Suitable'
export default function SuitableList() { export default function SuitableList() {
const { toCodeName, suitableSearchResults, isSearchLoading } = useSuitable() const { toCodeName, suitableSearchResults, isSearchLoading, filterSuitableDetail } = useSuitable()
const { selectedItems, addSelectedItem, removeSelectedItem } = useSuitableStore() const { selectedItems, addSelectedItem, removeSelectedItem } = useSuitableStore()
const [openItems, setOpenItems] = useState<Set<number>>(new Set())
const handleItemClick = (itemId: number) => { const handleItemClick = (itemId: number) => {
selectedItems.some((selected) => selected === itemId) ? removeSelectedItem(itemId) : addSelectedItem(itemId) selectedItems.some((selected) => selected === itemId) ? removeSelectedItem(itemId) : addSelectedItem(itemId)
} }
const toggleItemOpen = (itemId: number) => {
setOpenItems((prev) => {
const newOpenItems = new Set(prev)
newOpenItems.has(itemId) ? newOpenItems.delete(itemId) : newOpenItems.add(itemId)
return newOpenItems
})
}
// TODO: 추후 지붕재 적합성 데이터 CUD 구현 시 ×, ー 데이터 관리 필요 // TODO: 추후 지붕재 적합성 데이터 CUD 구현 시 ×, ー 데이터 관리 필요
const suitableCheck = (value: string) => { const suitableCheck = (value: string) => {
if (value === '×') { if (value === '×') {
return <i className="compliance-icon x" /> return (
<div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_x_icon.svg'} width={22} height={22} alt=""></Image>
</div>
)
} else if (value === 'ー') { } else if (value === 'ー') {
return <i className="compliance-icon quest" /> return (
<div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_quest_icon.svg'} width={22} height={22} alt=""></Image>
</div>
)
} else { } else {
return <i className="compliance-icon check" /> return (
<div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_check_icon.svg'} width={22} height={22} alt=""></Image>
</div>
)
} }
} }
const filterSuitableDetail = (mainId: number): SuitableDetail[] | undefined => {
const result: SuitableDetail[] = []
for (const subItem of suitableSearchResults?.suitableDetail ?? []) {
if (subItem.MAIN_ID > mainId) break
if (subItem.MAIN_ID === mainId) {
result.push(subItem)
}
}
return result
}
return ( return (
<> <>
{isSearchLoading ? ( {isSearchLoading ? (
<div>Loading...</div> <div>Loading...</div>
) : suitableSearchResults && suitableSearchResults.suitable.length > 0 ? ( ) : suitableSearchResults && suitableSearchResults.suitable.length > 0 ? (
suitableSearchResults.suitable.map((item: SuitableMain) => ( suitableSearchResults.suitable.map((item: SuitableMain) => (
<div className={`compliance-check-bx act`} key={item.ID}> <div className={`compliance-check-bx ${openItems.has(item.ID) ? 'act' : ''}`} key={item.ID}>
<div className="check-name-wrap"> <div className="check-name-wrap">
<div className="check-form-box com-tit"> <div className="check-form-box ">
<input type="checkbox" id={`ch${item.ID}`} /> <input type="checkbox" id={`ch${item.ID}`} onClick={() => handleItemClick(item.ID)} />
<label htmlFor={`ch${item.ID}`}>{item.PRODUCT_NAME}</label> <label htmlFor={`ch${item.ID}`}>{item.PRODUCT_NAME}</label>
</div> </div>
<div className="check-name-btn"> <div className="check-name-btn">
<button className="bx-btn" onClick={() => handleItemClick(item.ID)}></button> <button className="bx-btn" onClick={() => toggleItemOpen(item.ID)}></button>
</div> </div>
</div> </div>
<ul className="reference-list check"> <ul className="reference-list check">
<li className="reference-item"> {filterSuitableDetail(item.ID)?.map((subItem: SuitableDetail) => (
{filterSuitableDetail(item.ID)?.map((subItem: SuitableDetail) => ( <li className="reference-item" key={subItem.ID}>
<div className="check-item-wrap" key={subItem.ID}> <div className="check-item-wrap">
<div className="check-form-box com-txt"> <div className="check-form-box light">
<input type="checkbox" id={`ch${subItem.ID}`} /> <input type="checkbox" id={`ch${subItem.ID}`} />
<label htmlFor={`ch${subItem.ID}`}>{toCodeName(SUITABLE_HEAD_CODE.TRESTLE_MFPC_CD, subItem.TRESTLE_MFPC_CD)}</label> <label htmlFor={`ch${subItem.ID}`}>{toCodeName(SUITABLE_HEAD_CODE.TRESTLE_MFPC_CD, subItem.TRESTLE_MFPC_CD)}</label>
</div> </div>
<div className="compliance-icon-wrap"> <div className="compliance-icon-wrap">
{suitableCheck(subItem.TRESTLE_MANUFACTURER_PRODUCT_NAME)} {suitableCheck(subItem.TRESTLE_MANUFACTURER_PRODUCT_NAME)}
{subItem.MEMO && <i className="compliance-icon tip"></i>} {subItem.MEMO && (
<div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_tip_icon.svg'} width={22} height={22} alt=""></Image>
</div>
)}
</div> </div>
</div> </div>
))} </li>
</li> ))}
</ul> </ul>
</div> </div>
)) ))

View File

@ -82,6 +82,17 @@ export function useSuitable() {
enabled: true, enabled: true,
}) })
const filterSuitableDetail = (mainId: number): SuitableDetail[] | undefined => {
const result: SuitableDetail[] = []
for (const subItem of suitableSearchResults?.suitableDetail ?? []) {
if (subItem.MAIN_ID > mainId) break
if (subItem.MAIN_ID === mainId) {
result.push(subItem)
}
}
return result
}
return { return {
getSuitables, getSuitables,
getSuitableCommCode, getSuitableCommCode,
@ -91,5 +102,6 @@ export function useSuitable() {
suitableSearchResults, suitableSearchResults,
refetchBySearch, refetchBySearch,
isSearchLoading, isSearchLoading,
filterSuitableDetail,
} }
} }