diff --git a/.env.development b/.env.development index 4e7f5a9..6bc3000 100644 --- a/.env.development +++ b/.env.development @@ -8,8 +8,8 @@ NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 #1:1문의 api # NEXT_PUBLIC_INQUIRY_API_URL=http://1.248.227.176:38080 -# NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 -NEXT_PUBLIC_INQUIRY_API_URL=http://172.30.1.93:8120 +NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 +# NEXT_PUBLIC_INQUIRY_API_URL=http://172.30.1.93:8120 #QPARTNER 로그인 api diff --git a/src/app/api/qna/detail/route.ts b/src/app/api/qna/detail/route.ts index 124ec68..315c18e 100644 --- a/src/app/api/qna/detail/route.ts +++ b/src/app/api/qna/detail/route.ts @@ -13,7 +13,6 @@ export async function GET(request: Request) { try { const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/qna/detail?${queryStringFormatter(params)}`) - console.log('response.data detail:: ', response.data) if (response.status === 200) { return NextResponse.json(response.data) } diff --git a/src/app/api/qna/file/route.ts b/src/app/api/qna/file/route.ts index 13a9232..a122da6 100644 --- a/src/app/api/qna/file/route.ts +++ b/src/app/api/qna/file/route.ts @@ -9,13 +9,11 @@ export async function GET(request: Request) { return NextResponse.json({ error: 'encodeFileNo is required' }, { status: 400 }) } try { - const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/file/downloadFile`, { + const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/file/downloadFile`, { params: { encodeFileNo, }, }) - console.log('response.data:: ', response.data) - return NextResponse.json(response.data) } catch (error: any) { console.error(error.response) diff --git a/src/app/api/qna/list/route.ts b/src/app/api/qna/list/route.ts index 2f7a52a..f793b98 100644 --- a/src/app/api/qna/list/route.ts +++ b/src/app/api/qna/list/route.ts @@ -17,7 +17,6 @@ export async function GET(request: Request) { try { const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/qna/list?${queryStringFormatter(params)}`) - console.log('response.data:: ', response.data) if (response.status === 200) { return NextResponse.json(response.data) } diff --git a/src/app/api/qna/save/route.ts b/src/app/api/qna/save/route.ts index 3afc339..f51ae66 100644 --- a/src/app/api/qna/save/route.ts +++ b/src/app/api/qna/save/route.ts @@ -9,7 +9,6 @@ export async function POST(request: Request) { 'Content-Type': 'multipart/form-data', }, }) - console.log('response:: ', response) if (response.status === 200) { return NextResponse.json(response.data) } diff --git a/src/components/inquiry/Answer.tsx b/src/components/inquiry/Answer.tsx index 94b6152..76da68a 100644 --- a/src/components/inquiry/Answer.tsx +++ b/src/components/inquiry/Answer.tsx @@ -1,6 +1,5 @@ 'use client' -import { useInquiry } from '@/hooks/useInquiry' import { Inquiry } from '@/types/Inquiry' export default function Answer({ inquiryDetail, downloadFile }: { inquiryDetail: Inquiry; downloadFile: (encodeFileNo: number) => Promise }) { @@ -15,10 +14,7 @@ export default function Answer({ inquiryDetail, downloadFile }: { inquiryDetail:
回答
-
- 一次側接続は, 自動切替開閉器と住宅分電盤昼間遮断器との間に蓄電システム遮断器を配線する方法です. 二次側接続は, - 住宅分電盤週間ブレーカの二次側に蓄電システムブレーカを接続する -
+
{inquiryDetail?.ansContents}
ファイル添付
diff --git a/src/components/inquiry/RegistForm.tsx b/src/components/inquiry/RegistForm.tsx index 1e97130..dd02baa 100644 --- a/src/components/inquiry/RegistForm.tsx +++ b/src/components/inquiry/RegistForm.tsx @@ -4,18 +4,13 @@ import { useInquiry } from '@/hooks/useInquiry' import { useSessionStore } from '@/store/session' import { InquiryRequest } from '@/types/Inquiry' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useRouter } from 'next/navigation' export default function RegistForm() { const { saveInquiry, isSavingInquiry } = useInquiry() const { session } = useSessionStore() const router = useRouter() - // TODO: 세션 정보 적용 | 현재는 test용 정보 적용 - // useEffect(() => { - // setInquiryRequest({ ...inquiryRequest, regId: session?.userId ?? '', regUserNm: session?.userNm ?? '' }) - // }, [session]) - const [inquiryRequest, setInquiryRequest] = useState({ compCd: '5200', siteTpCd: 'QC', @@ -24,12 +19,26 @@ export default function RegistForm() { qnaClsSmlCd: null, title: '', contents: '', - regId: 'X112', - regUserNm: 'TEST', + regId: '', + regUserNm: '', regUserTelNo: null, - storeId: 'X112', + storeId: '', qstMail: '', }) + const requiredFieldNames = [ + { id: 'qnaClsLrgCd', name: 'お問い合わせタイプ' }, + { id: 'qnaClsMidCd', name: 'お問い合わせタイプ' }, + { id: 'regUserNm', name: '名前' }, + { id: 'qstMail', name: 'E-mail' }, + { id: 'title', name: 'お問い合わせタイトル' }, + { id: 'contents', name: 'お問い合わせ内容' }, + ] + + useEffect(() => { + if (session?.isLoggedIn) { + setInquiryRequest({ ...inquiryRequest, regId: session?.userId ?? '', regUserNm: session?.userNm ?? '', storeId: session?.storeId ?? '' }) + } + }, [session]) const [attachedFiles, setAttachedFiles] = useState([]) @@ -45,7 +54,25 @@ export default function RegistForm() { setAttachedFiles(attachedFiles.filter((_, i) => i !== index)) } + const focusOnRequiredField = (fieldId: string) => { + const element = document.getElementById(fieldId) + if (element) element.focus() + } + const handleSubmit = async () => { + const emptyField = requiredFieldNames.find((field) => inquiryRequest[field.id as keyof InquiryRequest] === '') + if (emptyField) { + alert(`${emptyField?.name}を入力してください。`) + focusOnRequiredField(emptyField?.id ?? '') + return + } + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + if (!emailRegex.test(inquiryRequest.qstMail)) { + alert('有効なメールアドレスを入力してください。') + focusOnRequiredField('qstMail') + return + } + const formData = new FormData() attachedFiles.forEach((file) => { formData.append('files', file) @@ -54,12 +81,10 @@ export default function RegistForm() { formData.append(key, value ?? '') }) - // FormData를 객체로 변환하여 확인 const formDataObj: Record = {} formData.forEach((value, key) => { formDataObj[key] = value }) - console.log('formData contents:', formDataObj) window.neoConfirm( 'お問い合わせを登録しますか? Hanwha Japanの担当者にお問い合わせメールが送信されます。', @@ -83,40 +108,40 @@ export default function RegistForm() {
@@ -130,6 +155,8 @@ export default function RegistForm() { type="text" placeholder="名前を書いてください" onChange={(e) => setInquiryRequest({ ...inquiryRequest, regUserNm: e.target.value })} + value={inquiryRequest.regUserNm} + id="regUserNm" /> @@ -141,6 +168,7 @@ export default function RegistForm() { type="text" placeholder="電話番号を書き留めてください" onChange={(e) => setInquiryRequest({ ...inquiryRequest, regUserTelNo: e.target.value })} + id="regUserTelNo" /> @@ -154,6 +182,7 @@ export default function RegistForm() { type="text" placeholder="E-mailを書いてください" onChange={(e) => setInquiryRequest({ ...inquiryRequest, qstMail: e.target.value })} + id="qstMail" /> @@ -167,6 +196,7 @@ export default function RegistForm() { type="text" placeholder="お問い合わせタイトルを記入してください" onChange={(e) => setInquiryRequest({ ...inquiryRequest, title: e.target.value })} + id="title" /> @@ -178,8 +208,7 @@ export default function RegistForm() { diff --git a/src/components/inquiry/list/ListForm.tsx b/src/components/inquiry/list/ListForm.tsx index 0118f58..bb41fb3 100644 --- a/src/components/inquiry/list/ListForm.tsx +++ b/src/components/inquiry/list/ListForm.tsx @@ -13,7 +13,6 @@ export default function ListForm() { setInquiryListRequest({ ...inquiryListRequest, schTitle: searchKeyword }) } } - const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleSearch() diff --git a/src/components/inquiry/list/ListTable.tsx b/src/components/inquiry/list/ListTable.tsx index 454dbb3..bf5ce88 100644 --- a/src/components/inquiry/list/ListTable.tsx +++ b/src/components/inquiry/list/ListTable.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react' import LoadMoreButton from '../../LoadMoreButton' import { useInquiry } from '@/hooks/useInquiry' import { InquiryList } from '@/types/Inquiry' -import { useRouter } from 'next/navigation' +import { usePathname, useRouter } from 'next/navigation' import { useInquiryFilterStore } from '@/store/inquiryFilterStore' import { useSessionStore } from '@/store/session' import ListForm from './ListForm' @@ -22,48 +22,66 @@ const badgeStyle = [ }, ] export default function ListTable() { - const [offset, setOffset] = useState(0) - const [hasMore, setHasMore] = useState(false) - const router = useRouter() + const pathname = usePathname() const { inquiryList } = useInquiry() - const { inquiryListRequest, setInquiryListRequest } = useInquiryFilterStore() + const { inquiryListRequest, setInquiryListRequest, reset } = useInquiryFilterStore() - const [heldInquiryList, setHeldInquiryList] = useState([]) + const [offset, setOffset] = useState(inquiryListRequest.startRow) + const [hasMore, setHasMore] = useState(false) + + const [heldInquiryList, setHeldInquiryList] = useState([]) const { session } = useSessionStore() useEffect(() => { - if (!inquiryList) return - setHeldInquiryList(inquiryList) - setHasMore(inquiryList.length > offset + 10) - }, [inquiryList, offset]) + setInquiryListRequest({ ...inquiryListRequest, startRow: 1, endRow: 10 }) + setHeldInquiryList([]) + setOffset(1) + setHasMore(false) + }, [pathname]) - console.log('heldInquiryList:: ', heldInquiryList) - console.log('inquiryList:: ', inquiryList) + useEffect(() => { + if (!session.isLoggedIn || !inquiryList) return + if (session.isLoggedIn) { + setInquiryListRequest({ ...inquiryListRequest, storeId: session.storeId ?? '', loginId: session.userId ?? '' }) + // setInquiryListRequest({ ...inquiryListRequest, storeId: 'X112', loginId: 'x112' }) + } + console.log('inquiryListRequest', inquiryListRequest) + if (inquiryList.length > 0 && inquiryList[0].totCnt > 0) { + if (inquiryListRequest.startRow > 1) { + const isDuplicate = inquiryList.every((newItem) => heldInquiryList.some((existingItem) => existingItem.qnaNo === newItem.qnaNo)) + if (isDuplicate) return + setHeldInquiryList((prev) => [...prev, ...inquiryList]) + } else { + setHeldInquiryList(inquiryList) + } + setHasMore(inquiryList[0].totCnt > inquiryListRequest.endRow) + } else { + setHeldInquiryList([]) + setHasMore(false) + } + }, [session, inquiryList, inquiryListRequest.startRow]) const handleMyInquiry = () => { setInquiryListRequest({ ...inquiryListRequest, schRegId: inquiryListRequest.schRegId ? null : session.userId }) } - const handleLoadMore = () => { - setOffset(offset + 10) - setInquiryListRequest({ ...inquiryListRequest, startRow: offset, endRow: offset + 10 }) - - setHeldInquiryList((prev) => [...prev, ...inquiryList]) - } - const handleFilter = (e: React.ChangeEvent) => { - console.log(e.target.value) - setHeldInquiryList(inquiryList.filter((inquiry: InquiryList) => inquiry.answerYn === e.target.value)) - if (e.target.value === '') { - setHeldInquiryList(inquiryList) + switch (e.target.value) { + case 'N': + setInquiryListRequest({ ...inquiryListRequest, schAnswerYn: 'N' }) + break + case 'Y': + setInquiryListRequest({ ...inquiryListRequest, schAnswerYn: 'Y' }) + break + default: + reset() + break } } - console.log('heldInquiryList:: ', heldInquiryList) - return ( <> @@ -87,23 +105,39 @@ export default function ListTable() {
合計 {heldInquiryList.length > 0 ? heldInquiryList[0].totCnt : 0}
-
    - {heldInquiryList.length > 0 && - heldInquiryList.map((inquiry: InquiryList) => ( -
  • router.push(`/inquiry/${inquiry.qnaNo}`)}> -
    -
    {inquiry.qnaClsLrgCd}
    -
    {inquiry.qstTitle}
    -
    {inquiry.regDt}
    -
    badge.id === inquiry.answerYn)?.color}`}> - {badgeStyle.find((badge) => badge.id === inquiry.answerYn)?.label} + {heldInquiryList.length === 0 || (heldInquiryList.length > 0 && heldInquiryList[0].totCnt === 0) ? ( +
    +
    照会されたデータがありません。
    +
    + ) : ( +
      + {heldInquiryList.length > 0 && + heldInquiryList.map((inquiry: InquiryList) => ( +
    • router.push(`/inquiry/${inquiry.qnaNo}`)}> +
      +
      + {inquiry.qnaClsLrgCd} + {inquiry.qnaClsMidCd} + {inquiry.qnaClsSmlCd} +
      +
      {inquiry.qstTitle}
      +
      {inquiry.regDt}
      +
      badge.id === inquiry.answerYn)?.color}`}> + {badgeStyle.find((badge) => badge.id === inquiry.answerYn)?.label} +
      -
    -
  • - ))} -
+ + ))} + + )}
- handleLoadMore()} /> + { + setInquiryListRequest({ ...inquiryListRequest, startRow: offset + 10, endRow: offset + 19 }) + setOffset(inquiryListRequest.startRow) + }} + />
diff --git a/src/hooks/useInquiry.ts b/src/hooks/useInquiry.ts index c49df3e..a497806 100644 --- a/src/hooks/useInquiry.ts +++ b/src/hooks/useInquiry.ts @@ -1,7 +1,9 @@ import { InquiryList, Inquiry, InquirySaveResponse } from '@/types/Inquiry' import { axiosInstance } from '@/libs/axios' -import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useInquiryFilterStore } from '@/store/inquiryFilterStore' +import { useMemo } from 'react' +import { useSessionStore } from '@/store/session' export function useInquiry( qnoNo?: number, @@ -17,6 +19,7 @@ export function useInquiry( } { const queryClient = useQueryClient() const { inquiryListRequest } = useInquiryFilterStore() + const { session } = useSessionStore() const { data: inquiryList, isLoading: isLoadingInquiryList } = useQuery({ queryKey: ['inquiryList', inquiryListRequest], @@ -31,16 +34,25 @@ export function useInquiry( return [] } }, + placeholderData: (previousData) => previousData, }) + const inquriyListData = useMemo(() => { + if (isLoadingInquiryList) { + return { inquiryList: inquiryList ?? [] } + } + return { + inquiryList: inquiryList ?? [], + } + }, [inquiryList, isLoadingInquiryList]) + const { data: inquiryDetail, isLoading: isLoadingInquiryDetail } = useQuery({ - queryKey: ['inquiryDetail', qnoNo, compCd], + queryKey: ['inquiryDetail', qnoNo, compCd, session?.userId], queryFn: async () => { try { const resp = await axiosInstance(null).get<{ data: Inquiry }>(`/api/qna/detail`, { - params: { qnoNo, compCd, langCd: 'JA', loginId: 'x112' }, + params: { qnoNo, compCd, langCd: 'JA', loginId: session?.userId ?? '' }, }) - console.log('resp.data.data:: ', resp.data.data) return resp.data.data } catch (error: any) { console.error(error.response) @@ -66,7 +78,7 @@ export function useInquiry( } return { - inquiryList: inquiryList ?? [], + inquiryList: inquriyListData.inquiryList, inquiryDetail: inquiryDetail ?? null, isLoadingInquiryList, isLoadingInquiryDetail, diff --git a/src/store/inquiryFilterStore.ts b/src/store/inquiryFilterStore.ts index af862c2..62f70df 100644 --- a/src/store/inquiryFilterStore.ts +++ b/src/store/inquiryFilterStore.ts @@ -11,15 +11,16 @@ export const useInquiryFilterStore = create((set) => ({ inquiryListRequest: { compCd: '5200', langCd: 'JA', - storeId: 'X112', + storeId: '', siteTpCd: 'QC', schTitle: null, schRegId: null, schFromDt: null, schToDt: null, - startRow: 0, + schAnswerYn: null, + startRow: 1, endRow: 10, - loginId: 'x112', + loginId: '', }, setInquiryListRequest: (inquiryListRequest) => set({ inquiryListRequest }), reset: () => @@ -27,15 +28,16 @@ export const useInquiryFilterStore = create((set) => ({ inquiryListRequest: { compCd: '5200', langCd: 'JA', - storeId: 'X112', + storeId: '', siteTpCd: 'QC', schTitle: '', schRegId: '', schFromDt: '', schToDt: '', - startRow: 0, - endRow: 50, - loginId: 'x112', + schAnswerYn: null, + startRow: 1, + endRow: 10, + loginId: '', }, }), })) diff --git a/src/types/Inquiry.ts b/src/types/Inquiry.ts index c876020..79ac368 100644 --- a/src/types/Inquiry.ts +++ b/src/types/Inquiry.ts @@ -7,6 +7,7 @@ export type InquiryListRequest = { schRegId: string | null //search regId schFromDt: string | null //search start date schToDt: string | null //search end date + schAnswerYn: string | null //search answer yn startRow: number //start row endRow: number //end row loginId: string //login id