feat: modify inquriy create parameter

- 문의 등록 시 이메일 파라미터 추가
This commit is contained in:
Dayoung 2025-05-16 11:01:39 +09:00
parent 4d6f5c0e01
commit 7066d01060
10 changed files with 143 additions and 97 deletions

View File

@ -6,10 +6,19 @@ export async function GET(request: Request) {
const encodeFileNo = searchParams.get('encodeFileNo')
if (!encodeFileNo) {
return NextResponse.json({ error: 'fileNo is required' }, { status: 400 })
return NextResponse.json({ error: 'encodeFileNo is required' }, { status: 400 })
}
const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/file/downloadFile?encodeFileNo=${encodeFileNo}`)
try {
const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/file/downloadFile`, {
params: {
encodeFileNo,
},
})
console.log('response.data:: ', response.data)
return NextResponse.json(response.data)
} catch (error: any) {
console.error(error.response)
return NextResponse.json({ error: error.response.data }, { status: 500 })
}
}

View File

@ -21,7 +21,6 @@ export async function GET(request: Request) {
if (response.status === 200) {
return NextResponse.json(response.data)
}
return NextResponse.json({ error: 'Failed to fetch qna list' }, { status: response.status })
} catch (error: any) {
console.error('Error fetching qna list:', error.response.data)

View File

@ -4,12 +4,9 @@ import { NextResponse } from 'next/server'
export async function POST(request: Request) {
const formData = await request.formData()
console.log('formData:: ', formData)
// const body = await request.json()
// console.log('body:: ', body)
try {
const response = await axios.post(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/qna/save`, formData)
console.log('response.data:: ', response.data)
if (response.status === 200) {
return NextResponse.json(response.data)

View File

@ -1,11 +1,9 @@
import ListForm from '@/components/inquiry/list/ListForm'
import ListTable from '@/components/inquiry/list/ListTable'
export default function page() {
return (
<>
<div className="sale-contents">
<ListForm />
<ListTable />
</div>
</>

View File

@ -3,19 +3,13 @@
import Answer from './Answer'
import { useInquiry } from '@/hooks/useInquiry'
import { useParams, useRouter } from 'next/navigation'
import { useState } from 'react'
export default function Detail() {
//todo: 답변 완료 표시를 위해 임시로 추가 해 놓은 state
// 추후에 api 작업 완료후 삭제
// 답변 완료 클래스 & 하단 답변내용 출력도
const params = useParams()
const id = params.id
const { inquiryDetail, downloadFile } = useInquiry(Number(id), '5200')
const router = useRouter()
const [inquiry, setInquiry] = useState<Boolean>(true)
return (
<>
@ -39,15 +33,7 @@ export default function Detail() {
</tr>
<tr>
<th></th>
<td>Hong gi</td>
</tr>
<tr>
<th></th>
<td>Kim</td>
</tr>
<tr>
<th></th>
<td>070-1234-5678</td>
<td>{inquiryDetail?.regNm}</td>
</tr>
<tr>
<th></th>
@ -66,17 +52,9 @@ export default function Detail() {
</div>
<div className="inquiry-detail-data">
<div className="inquiry-detail-category">
<span></span>
<span></span>
<span></span>
</div>
<div className="inquiry-detail-tit"></div>
<div className="inquiry-detail-txt">
.
<br />
.
<br />
.
<span>{inquiryDetail?.qnaClsLrgCd}</span>
<span>{inquiryDetail?.qnaClsMidCd}</span>
<span>{inquiryDetail?.qnaClsSmlCd}</span>
</div>
<div className="inquiry-detail-tit">{inquiryDetail?.qstTitle}</div>
<div className="inquiry-detail-txt">{inquiryDetail?.qstContents}</div>
@ -91,6 +69,11 @@ export default function Detail() {
</button>
</li>
))}
<li className="file-item">
<button className="file-item-bx" onClick={() => downloadFile(Number(1))}>
<div className="file-item-name">Test File</div>
</button>
</li>
</ul>
</div>
</div>

View File

@ -4,7 +4,7 @@ import { useInquiry } from '@/hooks/useInquiry'
import { useSessionStore } from '@/store/session'
import { InquiryRequest } from '@/types/Inquiry'
import { useEffect, useState } from 'react'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
export default function RegistForm() {
const { saveInquiry, isSavingInquiry } = useInquiry()
@ -20,14 +20,15 @@ export default function RegistForm() {
compCd: '5200',
siteTpCd: 'QC',
qnaClsLrgCd: '',
qnaClsMidCd: 'B02',
qnaClsMidCd: '',
qnaClsSmlCd: null,
title: '',
contents: null,
contents: '',
regId: 'X112',
regUserNm: 'TEST',
regUserTelNo: null,
storeId: null,
storeId: 'X112',
qstMail: '',
})
const [attachedFiles, setAttachedFiles] = useState<File[]>([])
@ -45,12 +46,30 @@ export default function RegistForm() {
}
const handleSubmit = async () => {
if (confirm('お問い合わせを登録しますか? Hanwha Japanの担当者にお問い合わせメールが送信されます。')) {
const res = await saveInquiry({ inquiryRequest, files: attachedFiles })
const formData = new FormData()
attachedFiles.forEach((file) => {
formData.append('files', file)
})
Object.entries(inquiryRequest).forEach(([key, value]) => {
formData.append(key, value ?? '')
})
// FormData를 객체로 변환하여 확인
const formDataObj: Record<string, any> = {}
formData.forEach((value, key) => {
formDataObj[key] = value
})
console.log('formData contents:', formDataObj)
window.neoConfirm(
'お問い合わせを登録しますか? Hanwha Japanの担当者にお問い合わせメールが送信されます。',
async () => {
const res = await saveInquiry(formData)
alert('保存されました。')
router.push(`/inquiry/${res.qnaNo}`)
}
return
},
() => null,
)
}
return (
@ -62,30 +81,42 @@ export default function RegistForm() {
<i className="import">*</i>
</div>
<div className="data-input">
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<select
className="select-form"
name=""
id="qnaClsLrgCd"
value={inquiryRequest.qnaClsLrgCd}
onChange={(e) => setInquiryRequest({ ...inquiryRequest, qnaClsLrgCd: e.target.value })}
>
<option value=""></option>
<option value="A01">A01</option>
<option value="A01"></option>
</select>
</div>
<div className="data-input mt5">
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<select
className="select-form"
name=""
id="qnaClsMidCd"
value={inquiryRequest.qnaClsMidCd}
onChange={(e) => setInquiryRequest({ ...inquiryRequest, qnaClsMidCd: e.target.value })}
>
<option value=""></option>
<option value="B02">B02</option>
<option value="B02"></option>
</select>
</div>
<div className="data-input mt5">
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<select
className="select-form"
name=""
id="qnaClsSmlCd"
value={inquiryRequest.qnaClsSmlCd ?? ''}
onChange={(e) => setInquiryRequest({ ...inquiryRequest, qnaClsSmlCd: e.target.value })}
>
<option value=""></option>
<option value="C05">C05</option>
<option value="C05"></option>
</select>
</div>
</div>
@ -94,27 +125,36 @@ export default function RegistForm() {
<i className="import">*</i>
</div>
<div className="data-input">
<input className="input-frame" type="text" placeholder="名前を書いてください" />
<input
className="input-frame"
type="text"
placeholder="名前を書いてください"
onChange={(e) => setInquiryRequest({ ...inquiryRequest, regUserNm: e.target.value })}
/>
</div>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<div className="data-input">
<input className="input-frame" type="text" placeholder="電話番号を書き留めてください" />
<input
className="input-frame"
type="text"
placeholder="電話番号を書き留めてください"
onChange={(e) => setInquiryRequest({ ...inquiryRequest, regUserTelNo: e.target.value })}
/>
</div>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit">
<i className="import">*</i>
E-mail <i className="import">*</i>
</div>
<div className="data-input">
<input className="input-frame" type="text" placeholder="名前を書いてください" />
</div>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<div className="data-input">
<input className="input-frame" type="text" placeholder="電話番号を書き留めてください" />
<input
className="input-frame"
type="text"
placeholder="E-mailを書いてください"
onChange={(e) => setInquiryRequest({ ...inquiryRequest, qstMail: e.target.value })}
/>
</div>
</div>
<div className="data-input-form-bx">
@ -122,7 +162,12 @@ export default function RegistForm() {
<i className="import">*</i>
</div>
<div className="data-input">
<input className="input-frame" type="text" placeholder="お問い合わせタイトルを記入してください" />
<input
className="input-frame"
type="text"
placeholder="お問い合わせタイトルを記入してください"
onChange={(e) => setInquiryRequest({ ...inquiryRequest, title: e.target.value })}
/>
</div>
</div>
<div className="data-input-form-bx">

View File

@ -5,8 +5,8 @@ import { useState } from 'react'
export default function ListForm() {
const router = useRouter()
const [searchKeyword, setSearchKeyword] = useState('')
const { inquiryListRequest, setInquiryListRequest } = useInquiryFilterStore()
const [searchKeyword, setSearchKeyword] = useState(inquiryListRequest.schTitle ?? '')
const handleSearch = () => {
if (searchKeyword.length >= 2) {

View File

@ -7,6 +7,7 @@ import { InquiryList } from '@/types/Inquiry'
import { useRouter } from 'next/navigation'
import { useInquiryFilterStore } from '@/store/inquiryFilterStore'
import { useSessionStore } from '@/store/session'
import ListForm from './ListForm'
const badgeStyle = [
{
@ -29,14 +30,23 @@ export default function ListTable() {
const { inquiryList } = useInquiry()
const { inquiryListRequest, setInquiryListRequest } = useInquiryFilterStore()
const [heldInquiryList, setHeldInquiryList] = useState<typeof inquiryList>([])
const { session } = useSessionStore()
useEffect(() => {
if (inquiryList.length !== 0) {
const hasMoreItems = inquiryList[0].totCnt > offset + 10
setHasMore(hasMoreItems)
if (inquiryList.length > 0) {
if (offset === 0) {
setHeldInquiryList(inquiryList)
} else {
setHasMore(false)
const remainingList = heldInquiryList.slice(offset, offset + 10)
if (JSON.stringify(remainingList) !== JSON.stringify(inquiryList)) {
setHeldInquiryList((prev) => [...prev, ...inquiryList])
}
}
setHasMore(inquiryList.length > offset + 10)
} else {
setHeldInquiryList([])
}
}, [inquiryList, offset])
@ -49,8 +59,19 @@ export default function ListTable() {
setInquiryListRequest({ ...inquiryListRequest, startRow: offset, endRow: offset + 10 })
}
const handleFilter = (e: React.ChangeEvent<HTMLSelectElement>) => {
console.log(e.target.value)
setHeldInquiryList(inquiryList.filter((inquiry: InquiryList) => inquiry.answerYn === e.target.value))
if (e.target.value === '') {
setHeldInquiryList(inquiryList)
}
}
console.log('heldInquiryList:: ', heldInquiryList)
return (
<>
<ListForm />
<div className="sale-frame">
<div className="inquiry-table-filter">
<div className="filter-check">
@ -60,7 +81,7 @@ export default function ListTable() {
</div>
</div>
<div className="filter-select">
<select className="select-form" name="" id="">
<select className="select-form" name="" id="" onChange={(e) => handleFilter(e)}>
<option value=""></option>
<option value="N"></option>
<option value="Y"></option>
@ -69,11 +90,11 @@ export default function ListTable() {
</div>
<div className="inquiry-list-wrap">
<div className="inquiry-list-tit">
<span>{inquiryList.length}</span>
<span>{heldInquiryList.length > 0 ? heldInquiryList[0].totCnt : 0}</span>
</div>
<ul className="inquiry-list">
{inquiryList.length > 0 &&
inquiryList.map((inquiry: InquiryList) => (
{heldInquiryList.length > 0 &&
heldInquiryList.map((inquiry: InquiryList) => (
<li className="inquiry-item" key={inquiry.qnaNo} onClick={() => router.push(`/inquiry/${inquiry.qnaNo}`)}>
<div className="inquiry-item-bx">
<div className="inquiry-item-category">{inquiry.qnaClsLrgCd}</div>

View File

@ -12,10 +12,10 @@ export function useInquiry(
inquiryDetail: Inquiry | null
isLoadingInquiryDetail: boolean
isSavingInquiry: boolean
saveInquiry: (params: { inquiryRequest: InquiryRequest; files: File[] }) => Promise<InquirySaveResponse>
saveInquiry: (formData: FormData) => Promise<InquirySaveResponse>
downloadFile: (encodeFileNo: number) => Promise<File>
} {
const { session } = useSessionStore()
// const { session } = useSessionStore()
const queryClient = useQueryClient()
const { inquiryListRequest } = useInquiryFilterStore()
@ -41,6 +41,7 @@ export function useInquiry(
const resp = await axiosInstance(null).get<{ data: Inquiry }>(`/api/qna/detail`, {
params: { qnoNo, compCd, langCd: 'JA', loginId: 'x112' },
})
console.log('resp.data.data:: ', resp.data.data)
return resp.data.data
} catch (error: any) {
console.error(error.response)
@ -51,15 +52,7 @@ export function useInquiry(
})
const { mutateAsync: saveInquiry, isPending: isSavingInquiry } = useMutation({
mutationFn: async ({ inquiryRequest, files }: { inquiryRequest: InquiryRequest; files: File[] }) => {
const formData = new FormData()
Object.entries(inquiryRequest).forEach(([key, value]) => {
formData.append(key, value ?? '')
})
files.forEach((file) => {
formData.append('files', file)
})
mutationFn: async (formData: FormData) => {
const resp = await axiosInstance(null).post<{ data: InquirySaveResponse }>('/api/qna/save', formData)
return resp.data.data
},

View File

@ -75,11 +75,12 @@ export type InquiryRequest = {
qnaClsMidCd: string //qna CLS Mid Code
qnaClsSmlCd: string | null //qna CLS Small Code
title: string //title
contents: string | null //contents
contents: string //contents
regId: string //registration Userid
storeId: string | null //store id
storeId: string //store id
regUserNm: string //registration User name
regUserTelNo: string | null //registration User tel number
qstMail: string //mail
}
export type InquirySaveResponse = {