Merge pull request 'dev' (#52) from dev into dev-deploy
Reviewed-on: #52
This commit is contained in:
commit
03ec99dbb4
9
src/app/community/qna/page.jsx
Normal file
9
src/app/community/qna/page.jsx
Normal file
@ -0,0 +1,9 @@
|
||||
import Qna from '@/components/community/Qna'
|
||||
|
||||
export default async function CommunityQnaPage() {
|
||||
return (
|
||||
<>
|
||||
<Qna />
|
||||
</>
|
||||
)
|
||||
}
|
||||
214
src/components/community/Qna.jsx
Normal file
214
src/components/community/Qna.jsx
Normal file
@ -0,0 +1,214 @@
|
||||
'use client'
|
||||
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
|
||||
import Search from '@/components/community/Search'
|
||||
import Pagination from '@/components/community/Pagination'
|
||||
|
||||
import { useContext } from 'react'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useResetRecoilState, useRecoilValue, useRecoilState } from 'recoil'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
|
||||
import { searchState } from '@/store/boardAtom'
|
||||
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
import QnaBoardDetailModal from '@/components/community/modal/QnaDetailModal'
|
||||
import { sessionStore } from '@/store/commonAtom'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
|
||||
export default function Qna() {
|
||||
const { getMessage } = useMessage()
|
||||
const resetSearch = useResetRecoilState(searchState)
|
||||
const [isInitialized, setIsInitialized] = useState(false)
|
||||
|
||||
//const search = useRecoilValue(searchState)
|
||||
const [searchForm, setSearchForm] = useRecoilState(searchState)
|
||||
const { findCommonCode } = useCommonCode()
|
||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||
const { get } = useAxios()
|
||||
const [boardList, setBoardList] = useState([])
|
||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||
const [search, setSearch] = useRecoilState(searchState)
|
||||
// 팝업 관련
|
||||
const [open, setOpen] = useState(false)
|
||||
const [modalQnaNo, setModalQnaNo] = useState('')
|
||||
const [modalQnaType, setModalQnaType] = useState('')
|
||||
|
||||
// 목록 조회
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
setIsGlobalLoading(true)
|
||||
const startRow = (search.currentPage - 1) * search.pageBlock > 0 ? (search.currentPage - 1) * search.pageBlock + 1 : 1
|
||||
const endRow = search.currentPage * search.pageBlock
|
||||
|
||||
const url = `/api/board/list`
|
||||
const params = new URLSearchParams({
|
||||
schNoticeTpCd : 'QC',
|
||||
schNoticeClsCd: 'QNA',
|
||||
compCd : 5200,
|
||||
storeId : sessionState.storeId,
|
||||
loginId : sessionState.userId,
|
||||
schTitle : search.searchValue ? search.searchValue : '',
|
||||
startRow : startRow,
|
||||
endRow : endRow,
|
||||
schMainYn : 'N',
|
||||
siteTpCd : 'QC',
|
||||
})
|
||||
const apiUrl = `${url}?${params.toString()}`
|
||||
|
||||
const resultData = await get({ url: apiUrl })
|
||||
|
||||
if (resultData) {
|
||||
if (resultData.result.code === 200) {
|
||||
if (resultData.data.length > 0) {
|
||||
setBoardList(resultData.data)
|
||||
setSearch({ ...search, totalCount: resultData.data[0].totCnt })
|
||||
} else {
|
||||
setBoardList([])
|
||||
setSearch({ ...search, totalCount: 0 })
|
||||
}
|
||||
} else {
|
||||
alert(resultData.result.message)
|
||||
}
|
||||
}
|
||||
setIsGlobalLoading(false)
|
||||
}
|
||||
|
||||
fetchData()
|
||||
}, [search.currentPage, search.searchValue, search.pageBlock, search.searchFlag])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (search.mainFlag === 'N') {
|
||||
resetSearch()
|
||||
} else {
|
||||
//메인에서 FAQ 조회 왔을때 로딩바 해제
|
||||
setIsGlobalLoading(false)
|
||||
setSearchForm({ ...searchForm, mainFlag: 'N' })
|
||||
}
|
||||
setIsInitialized(true)
|
||||
|
||||
//문의구분코드
|
||||
// const codeL = findCommonCode(204200)
|
||||
// const codeM = findCommonCode(204300)
|
||||
// const codeS = findCommonCode(204400)
|
||||
|
||||
|
||||
|
||||
}, [])
|
||||
|
||||
if (!isInitialized) {
|
||||
return null
|
||||
}
|
||||
|
||||
const boardType = {
|
||||
boardTitle: getMessage('qna.title'),
|
||||
subTitle: getMessage('qna.sub.title'),
|
||||
clsCode: 'QNA',
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="sub-header">
|
||||
<div className="sub-header-inner">
|
||||
<ul className="sub-header-title-wrap">
|
||||
<li className="title-item">
|
||||
<Link className="sub-header-title" href={'#'}>
|
||||
{getMessage('qna.title')}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="sub-header-location">
|
||||
<li className="location-item">
|
||||
<span className="home">
|
||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
||||
</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.community')}</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('qna.title')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sub-content">
|
||||
<div className="sub-content-inner">
|
||||
<div className="sub-table-box">
|
||||
<Search title={boardType.boardTitle} subTitle={boardType.subTitle} isSelectUse={true} clsCode={boardType.clsCode} />
|
||||
{/*<QnaTable clsCode={boardType.clsCode} />*/}
|
||||
<div className="community-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col width={100}/>
|
||||
<col width={150}/>
|
||||
<col />
|
||||
<col width={150}/>
|
||||
<col width={150}/>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{boardList.length > 0 ? (
|
||||
boardList?.map((board) => (
|
||||
<tr
|
||||
key={board.qnaNo}
|
||||
onClick={() => {
|
||||
setOpen(true)
|
||||
setModalQnaNo(board.qnaNo)
|
||||
setModalQnaType("["+board?.qnaClsLrgCd+"/"+board?.qnaClsMidCd+"/"+board?.qnaClsSmlCd+"]")
|
||||
}}
|
||||
>
|
||||
<td className="al-c">
|
||||
{/* 번호 */}
|
||||
{board.totCnt - board.rowNumber + 1}
|
||||
</td>
|
||||
{/* 답변 */}
|
||||
{board?.answerYn === 'Y'? (<td className="al-c "> {getMessage('qna.list.header.answer.yes')}</td>) : (<td className="al-c org"> {getMessage('qna.list.header.answer.no')}</td>)}
|
||||
<td>
|
||||
<div className="mb5">[{board?.qnaClsLrgCd} / {board?.qnaClsMidCd} / {board?.qnaClsSmlCd}]</div>
|
||||
{/* 제목 */}
|
||||
<div className="text-frame">
|
||||
<div className="text-overflow">{board.title}{board.qstTitle}</div>
|
||||
{board.attachYn === 'Y' && <span className="clip"></span>}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="renewal">
|
||||
{/*{board.uptDt && (*/}
|
||||
{/* <>*/}
|
||||
{/* (<span>{getMessage('board.uptDt')}</span> : {board.uptDt})*/}
|
||||
{/* </>*/}
|
||||
{/*)}*/}
|
||||
{board.regUserNm}
|
||||
</div>
|
||||
</td>
|
||||
<td className="al-c">
|
||||
{/* 등록일 */}
|
||||
{board.regDt.split(' ')[0]}
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan={4} className="al-c">
|
||||
{getMessage('common.message.no.data')}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<Pagination />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{open && <QnaBoardDetailModal qnaNo={modalQnaNo} setOpen={setOpen} qnaType = {modalQnaType} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -4,10 +4,11 @@ import { searchState } from '@/store/boardAtom'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { useState } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import QnaRegModal from '@/components/community/modal/QnaRegModal'
|
||||
|
||||
export default function Search({ title = '', subTitle = '', isSelectUse = false }) {
|
||||
export default function Search({ title = '', subTitle = '', isSelectUse = false, clsCode = '' }) {
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const [open, setOpen] = useState(false)
|
||||
const search = useRecoilValue(searchState)
|
||||
const [searchForm, setSearchForm] = useRecoilState(searchState)
|
||||
|
||||
@ -32,7 +33,13 @@ export default function Search({ title = '', subTitle = '', isSelectUse = false
|
||||
} else {
|
||||
setSearchView(false)
|
||||
setSearchViewText('')
|
||||
setSearchForm({ ...searchForm, currentPage: 1, searchValue: '', pageBlock: block, searchFlag: !searchForm.searchFlag })
|
||||
setSearchForm({
|
||||
...searchForm,
|
||||
currentPage: 1,
|
||||
searchValue: '',
|
||||
pageBlock : block,
|
||||
searchFlag : !searchForm.searchFlag,
|
||||
})
|
||||
}
|
||||
// 조회 후 값 비워주기
|
||||
setSearchValue('')
|
||||
@ -57,7 +64,10 @@ export default function Search({ title = '', subTitle = '', isSelectUse = false
|
||||
onKeyDown={handleKeyDown}
|
||||
value={searchValue}
|
||||
/>
|
||||
<button type="button" className="community-search-ico" onClick={() => handleSearch(searchValue, selectPageBlock)}></button>
|
||||
|
||||
<button type="button" className="community-search-ico"
|
||||
onClick={() => handleSearch(searchValue, selectPageBlock)}></button>
|
||||
|
||||
</div>
|
||||
{searchView && (
|
||||
<div className="community-search-keyword">
|
||||
@ -92,6 +102,14 @@ export default function Search({ title = '', subTitle = '', isSelectUse = false
|
||||
</div>
|
||||
{isSelectUse && (
|
||||
<div className="left-unit-box">
|
||||
{clsCode === 'QNA' &&
|
||||
<div>
|
||||
<button className="btn-origin navy mr10"
|
||||
onClick={() => {
|
||||
setOpen(true)
|
||||
}}> {getMessage('qna.sub.btn.inquiry')}</button>
|
||||
</div>
|
||||
}
|
||||
<div className="select-box" style={{ width: '80px' }}>
|
||||
<select
|
||||
className="select-light black"
|
||||
@ -112,6 +130,7 @@ export default function Search({ title = '', subTitle = '', isSelectUse = false
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{open && <QnaRegModal setOpen={setOpen} setReload={handleSearch} searchValue={searchValue ? searchValue : searchViewText} selectPageBlock = {selectPageBlock}/>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
127
src/components/community/modal/QnaDetailModal.jsx
Normal file
127
src/components/community/modal/QnaDetailModal.jsx
Normal file
@ -0,0 +1,127 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { handleFileDown } from '@/util/board-utils'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { sessionStore } from '@/store/commonAtom'
|
||||
import { useRecoilState } from 'recoil'
|
||||
|
||||
export default function QnaDetailModal({ qnaNo, setOpen, qnaType }) {
|
||||
const { getMessage } = useMessage()
|
||||
// api 조회 관련
|
||||
const { get } = useAxios()
|
||||
const [boardDetail, setBoardDetail] = useState({})
|
||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||
|
||||
useEffect(() => {
|
||||
// 상세 조회
|
||||
const fetchDetail = async (qnaNo) => {
|
||||
const url = `/api/board/detail`
|
||||
const params = new URLSearchParams({
|
||||
noticeNo : qnaNo,
|
||||
qnaNo : qnaNo,
|
||||
schNoticeClsCd: 'QNA',
|
||||
compCd : 5200,
|
||||
loginId : sessionState.userId,
|
||||
langCd : 'JA',
|
||||
})
|
||||
const apiUrl = `${url}?${params.toString()}`
|
||||
|
||||
const resultData = await get({ url: apiUrl })
|
||||
|
||||
if (resultData) {
|
||||
if (resultData.result.code === 200) {
|
||||
const boardDetail = resultData.data
|
||||
setBoardDetail(boardDetail)
|
||||
} else {
|
||||
alert(resultData.result.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fetchDetail(qnaNo)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div key={qnaNo} className="modal-popup community">
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
className="modal-close"
|
||||
onClick={() => {
|
||||
setOpen(false)
|
||||
}}
|
||||
>
|
||||
{getMessage('board.sub.btn.close')}
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="oneonone-header-wrap">
|
||||
<div className="oneonone-title"> {qnaType} {boardDetail.qstTitle}</div>
|
||||
<div className="oneonone-infor">
|
||||
<div className="profile">{boardDetail.regUserNm}</div>
|
||||
<div className="date">{boardDetail.regDt}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="oneonone-detail">
|
||||
{boardDetail.listFile && (
|
||||
<dl className="community_detail-file-wrap">
|
||||
<dt>{getMessage('qna.detail.sub.fileList')}</dt>
|
||||
{boardDetail.listFile.map((boardFile) => (
|
||||
<dd key={boardFile.encodeFileNo}>
|
||||
<button type="button" className="down" onClick={() => handleFileDown(boardFile.fileNo, 'N')}>
|
||||
{boardFile.srcFileNm}
|
||||
</button>
|
||||
</dd>
|
||||
))}
|
||||
</dl>
|
||||
)}
|
||||
<div
|
||||
className="community_detail-inner"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: boardDetail.qstContents ? boardDetail.qstContents.replaceAll('\n', '<br/>') : '',
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
{boardDetail?.answerYn === 'Y' && (
|
||||
<div className="oneonone-answer">
|
||||
<div className="answer-title-wrap">
|
||||
<div className="answer-title">Hanwha Japan {getMessage('qna.detail.sub.answer')}</div>
|
||||
<div className="oneonone-infor">
|
||||
<div className="profile">{boardDetail.ansRegNm}</div>
|
||||
<div className="date">{boardDetail.ansRegDt}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="community_detail-inner"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: boardDetail.ansContents ? boardDetail.ansContents.replaceAll('\n', '<br/>') : '',
|
||||
}}
|
||||
></div>
|
||||
{boardDetail.ansListFile && (
|
||||
<dl className="community_detail-file-wrap">
|
||||
<dt>{getMessage('qna.detail.sub.fileList')}</dt>
|
||||
{boardDetail.ansListFile.map((boardFile) => (
|
||||
<dd key={boardFile.encodeFileNo}>
|
||||
<button type="button" className="down" onClick={() => handleFileDown(boardFile.fileNo, 'N')}>
|
||||
{boardFile.srcFileNm}
|
||||
</button>
|
||||
</dd>
|
||||
))}
|
||||
</dl>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
140
src/components/community/modal/QnaFileUploader.jsx
Normal file
140
src/components/community/modal/QnaFileUploader.jsx
Normal file
@ -0,0 +1,140 @@
|
||||
'use client'
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
|
||||
export default function QnaFileUploader({ uploadFiles, setUploadFiles, qnaData, setQnaData }) {
|
||||
const fileInputRef = useRef(null)
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const { swalFire } = useSwal()
|
||||
|
||||
const handleButtonClick = (e) => {
|
||||
e.preventDefault()
|
||||
fileInputRef.current.click()
|
||||
}
|
||||
|
||||
const onChangeFiles = async (e) => {
|
||||
if (e.target.files.length <= 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const fileList = []
|
||||
let passFlag = true
|
||||
const allowedFileTypes = [
|
||||
'image/',
|
||||
'application/pdf',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PPTX 형식
|
||||
'application/vnd.ms-powerpoint', // PPT 형식
|
||||
]
|
||||
Array.from(e.target.files).forEach((file) => {
|
||||
//엑셀, pdf, 이미지
|
||||
const fileType = file.type
|
||||
if (!allowedFileTypes.some((type) => fileType.includes(type))) {
|
||||
passFlag = false
|
||||
} else {
|
||||
fileList.push({ data: file, id: uuidv4() })
|
||||
}
|
||||
})
|
||||
|
||||
if (!passFlag) {
|
||||
swalFire({ text: getMessage('estimate.detail.fileList.extCheck'), type: 'alert', icon: 'error' })
|
||||
}
|
||||
|
||||
setUploadFiles([...uploadFiles, ...fileList])
|
||||
setQnaData({...qnaData, files:[...uploadFiles, ...fileList]})
|
||||
e.target.value = ''
|
||||
}
|
||||
|
||||
const deleteFile = (id) => {
|
||||
setUploadFiles(uploadFiles.filter((file) => file.id !== id))
|
||||
setQnaData({...qnaData, files:uploadFiles.filter((file) => file.id !== id)})
|
||||
}
|
||||
|
||||
const handleDrop = (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const fileList = []
|
||||
let passFlag = true
|
||||
const allowedFileTypes = [
|
||||
'image/',
|
||||
'application/pdf',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PPTX 형식
|
||||
'application/vnd.ms-powerpoint', // PPT 형식
|
||||
]
|
||||
|
||||
Array.from(e.dataTransfer.files).forEach((file) => {
|
||||
//엑셀, pdf, 이미지
|
||||
let fileType = file.type
|
||||
if (!allowedFileTypes.some((type) => fileType.includes(type))) {
|
||||
passFlag = false
|
||||
} else {
|
||||
fileList.push({ data: file, id: uuidv4() })
|
||||
}
|
||||
})
|
||||
|
||||
if (!passFlag) {
|
||||
swalFire({ text: getMessage('estimate.detail.fileList.extCheck'), type: 'alert', icon: 'error' })
|
||||
}
|
||||
|
||||
setUploadFiles([...uploadFiles, ...fileList])
|
||||
setQnaData({...qnaData, files:[...uploadFiles, ...fileList]})
|
||||
}
|
||||
|
||||
const handleDragOver = (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
const handleDragEnd = (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
const handleDragLeave = (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
<div className="design-request-grid mt15">
|
||||
<div className="design-request-count">
|
||||
<div className="design-request-grid-tit">{getMessage("qna.reg.header.fileList")}</div>
|
||||
<div className="btn-area one-on-one">
|
||||
<label className="file-upload" htmlFor="img" onClick={handleButtonClick}>
|
||||
Attach File
|
||||
</label>
|
||||
<input type="file" multiple name="file" ref={fileInputRef} style={{ display: 'none' }} onChange={(e) => onChangeFiles(e)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="drag-file-box one-on-one">
|
||||
<div className="drag-file-area"
|
||||
draggable
|
||||
onDrop={(e) => handleDrop(e)}
|
||||
onDragOver={(e) => handleDragOver(e)}
|
||||
onDragEnd={(e) => handleDragEnd(e)}
|
||||
onDragLeave={(e) => handleDragLeave(e)}>
|
||||
<p>Drag file here</p>
|
||||
<ul className="file-list">
|
||||
{uploadFiles.length > 0 &&
|
||||
uploadFiles.map((file) => (
|
||||
<li className="file-item" key={file.id}>
|
||||
<span>
|
||||
{file.data.name} <button className="delete" onClick={() => deleteFile(file.id)}></button>
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
412
src/components/community/modal/QnaRegModal.jsx
Normal file
412
src/components/community/modal/QnaRegModal.jsx
Normal file
@ -0,0 +1,412 @@
|
||||
'use client'
|
||||
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { sessionStore } from '@/store/commonAtom'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import QnaFileUploader from '@/components/community/modal/QnaFileUploader'
|
||||
import { useContext, useEffect, useRef, useState } from 'react'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import Select from 'react-select'
|
||||
import dayjs from 'dayjs'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { e } from 'mathjs'
|
||||
|
||||
|
||||
export default function QnaRegModal({ setOpen, setReload, searchValue, selectPageBlock }) {
|
||||
const { getMessage } = useMessage()
|
||||
const [fileList, setFileList] = useState([])
|
||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
const [files, setFiles] = useState([])
|
||||
const [qnaData, setQnaData] = useState([])
|
||||
const [closeMdFlg, setCloseMdFlg] = useState(true)
|
||||
const [closeSmFlg, setCloseSmFlg] = useState(true)
|
||||
const qnaTypeLgCodeRef = useRef(null)
|
||||
const qnaTypeMdCodeRef = useRef(null)
|
||||
const qnaTypeSmCodeRef = useRef(null)
|
||||
const regUserNmRef = useRef(null)
|
||||
const regUserTelNoRef = useRef(null)
|
||||
const titleRef = useRef(null)
|
||||
const contentsRef = useRef(null)
|
||||
const { findCommonCode } = useCommonCode()
|
||||
const [qnaTypeLgCodeList, setQnaTypeLgCodeList] = useState([])
|
||||
const [qnaTypeMdCodeList, setQnaTypeMdCodeList] = useState([])
|
||||
const [qnaTypeSmCodeList, setQnaTypeSmCodeList] = useState([])
|
||||
const [phoneNumber, setPhoneNumber] = useState("");
|
||||
const { swalFire } = useSwal()
|
||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||
const [isBtnDisable, setIsBtnDisable] = useState(false);
|
||||
const { promiseGet, post, promisePost } = useAxios(globalLocaleState)
|
||||
|
||||
let fileCheck = false;
|
||||
const regPhoneNumber = (e) => {
|
||||
const result = e.target.value
|
||||
.replace(/[^0-9.]/g, "")
|
||||
//.replace(/^(\d{0,3})(\d{0,4})(\d{0,4})$/g, "$1-$2-$3")
|
||||
//.replace(/(-{1,2})$/g, "");
|
||||
//setPhoneNumber(result);
|
||||
|
||||
setQnaData({...qnaData, regUserTelNo: result })
|
||||
}
|
||||
|
||||
const fileUploadProps = {
|
||||
uploadFiles: files,
|
||||
setUploadFiles: setFiles,
|
||||
|
||||
}
|
||||
|
||||
// const fileSave = (qnaData, fileUploadProps) => {
|
||||
// return qnaData.files.push(fileUploadProps.uploadFiles)
|
||||
// }
|
||||
|
||||
const initQnaReg = async () => {
|
||||
|
||||
|
||||
regUserNmRef.current.value = ''
|
||||
regUserTelNoRef.current.value = ''
|
||||
qnaTypeLgCodeRef.current.setValue();
|
||||
qnaTypeMdCodeRef.current.setValue();
|
||||
qnaTypeSmCodeRef.current.setValue();
|
||||
titleRef.current.value = ''
|
||||
contentsRef.current.value = ''
|
||||
|
||||
//setQnaData([])
|
||||
|
||||
setQnaData({
|
||||
...qnaData,
|
||||
compCd: "5200",
|
||||
siteTpCd: "QC",
|
||||
schNoticeClsCd: "QNA",
|
||||
regId: sessionState.userId,
|
||||
storeId: sessionState.userId,
|
||||
qstMail : sessionState.email
|
||||
})
|
||||
|
||||
const codeL = findCommonCode(204200)
|
||||
if (codeL != null) {
|
||||
setQnaTypeLgCodeList(codeL)
|
||||
}
|
||||
setIsGlobalLoading(false)
|
||||
setIsBtnDisable(false);
|
||||
}
|
||||
const onChangeQnaTypeL = (e) => {
|
||||
if(e === undefined || e === null) return;
|
||||
const codeM = findCommonCode(204300)
|
||||
if (codeM != null) {
|
||||
|
||||
let codeList = []
|
||||
|
||||
codeM.map((item) => {
|
||||
|
||||
if(item.clRefChr1 === e.clCode) {
|
||||
codeList.push(item);
|
||||
|
||||
}
|
||||
})
|
||||
setQnaTypeMdCodeList(codeList)
|
||||
setQnaData({ ...qnaData, qnaClsLrgCd:e.clCode})
|
||||
setCloseMdFlg(false)
|
||||
qnaTypeMdCodeRef.current.setValue();
|
||||
qnaTypeSmCodeRef.current.setValue();
|
||||
}
|
||||
|
||||
}
|
||||
const onChangeQnaTypeM = (e) => {
|
||||
|
||||
if(e === undefined || e === null) return;
|
||||
const codeS = findCommonCode(204400)
|
||||
if (codeS != null) {
|
||||
|
||||
let codeList = []
|
||||
|
||||
codeS.map((item) => {
|
||||
|
||||
if (item.clRefChr1 === e.clCode) {
|
||||
codeList.push(item);
|
||||
|
||||
}
|
||||
})
|
||||
setQnaTypeSmCodeList(codeList)
|
||||
setQnaData({ ...qnaData, qnaClsMidCd: e.clCode })
|
||||
setCloseSmFlg(false)
|
||||
qnaTypeSmCodeRef.current.setValue();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
const onChangeQnaTypeS = (e) => {
|
||||
if(e === undefined || e === null) return;
|
||||
setQnaData({ ...qnaData, qnaClsSmlCd:e.clCode})
|
||||
}
|
||||
|
||||
const onFileSave = () => {
|
||||
const formData= []
|
||||
if(fileUploadProps.uploadFiles.length === 0) return;
|
||||
if(!fileCheck) return;
|
||||
|
||||
fileUploadProps.uploadFiles.forEach((file) => {
|
||||
console.log("file::::::::",file)
|
||||
formData.push(file)
|
||||
|
||||
})
|
||||
setQnaData({ ...qnaData, files:formData })
|
||||
fileCheck = false;
|
||||
}
|
||||
|
||||
const handleQnaSubmit = async () => {
|
||||
//필수 체크
|
||||
|
||||
//console.log("1::::",qnaData)
|
||||
|
||||
|
||||
let regUserNm = qnaData?.regUserNm??'';
|
||||
|
||||
if (regUserNm.trim().length === 0) {
|
||||
|
||||
regUserNmRef.current.value = '';
|
||||
regUserNmRef.current.focus()
|
||||
swalFire({
|
||||
text: getMessage('qna.reg.alert.require.regUserNm'),
|
||||
type: 'alert',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
let qnaClsLrgCd = qnaData?.qnaClsLrgCd??'';
|
||||
let qnaClsMidCd = qnaData?.qnaClsMidCd??'';
|
||||
|
||||
if (qnaClsLrgCd.trim().length === 0 || qnaClsMidCd.trim().length === 0 ) {
|
||||
(qnaClsLrgCd.trim().length === 0)?qnaTypeLgCodeRef.current.focus():qnaTypeMdCodeRef.current.focus()
|
||||
swalFire({
|
||||
text: getMessage('qna.reg.alert.select.type'),
|
||||
type: 'alert',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
let title = qnaData?.title??'';
|
||||
|
||||
if (title.trim().length === 0) {
|
||||
titleRef.current.value = '';
|
||||
titleRef.current.focus()
|
||||
swalFire({
|
||||
text: getMessage('qna.reg.alert.require.title'),
|
||||
type: 'alert',
|
||||
})
|
||||
return false
|
||||
}
|
||||
//console.log("5::::",qnaData)
|
||||
let contents = qnaData?.contents??'';
|
||||
|
||||
if (contents.trim().length === 0) {
|
||||
contentsRef.current.value = '';
|
||||
contentsRef.current.focus()
|
||||
swalFire({
|
||||
text: getMessage('qna.reg.alert.require.contents'),
|
||||
type: 'alert',
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
const formData = new FormData()
|
||||
if(qnaData?.files?.length > 0) {
|
||||
qnaData?.files.forEach((file) => {
|
||||
formData.append('files', file.data)
|
||||
})
|
||||
}
|
||||
formData.append("compCd", qnaData.compCd)
|
||||
formData.append("siteTpCd", qnaData.siteTpCd)
|
||||
formData.append("qnaClsLrgCd", qnaData.qnaClsLrgCd)
|
||||
formData.append("qnaClsMidCd", qnaData.qnaClsMidCd)
|
||||
formData.append("qnaClsSmlCd", qnaData.qnaClsSmlCd)
|
||||
formData.append("title", qnaData.title)
|
||||
formData.append("contents", qnaData.contents)
|
||||
formData.append("regId", qnaData.regId)
|
||||
formData.append("storeId", qnaData.storeId)
|
||||
formData.append("regUserNm", qnaData.regUserNm)
|
||||
formData.append("regUserTelNo", qnaData.regUserTelNo)
|
||||
formData.append("qstMail", qnaData.qstMail)
|
||||
formData.append("schNoticeClsCd", qnaData.schNoticeClsCd)
|
||||
|
||||
|
||||
|
||||
//console.log(Array.from(formData));
|
||||
|
||||
swalFire({
|
||||
html: getMessage('qna.reg.confirm.save'),
|
||||
type: 'confirm',
|
||||
confirmFn: async () => {
|
||||
|
||||
setIsBtnDisable(true);
|
||||
setIsGlobalLoading(true)
|
||||
|
||||
try {
|
||||
|
||||
const apiUrl = 'api/board'
|
||||
//console.log("7::::",qnaData)
|
||||
await post({ url: `${apiUrl}/saveQna`, data: formData }).then((res) => {
|
||||
if (res?.result.code === 200) {
|
||||
//qnaData.newFileList = []
|
||||
setIsGlobalLoading(false)
|
||||
swalFire({ text: getMessage('qna.reg.alert.save'), type: 'alert' })
|
||||
setOpen(false)
|
||||
setReload(searchValue, selectPageBlock);
|
||||
}
|
||||
setIsGlobalLoading(false)
|
||||
setIsBtnDisable(false)
|
||||
swalFire({ text: getMessage('qna.reg.alert.saveFail'), type: 'alert', icon: 'error' })
|
||||
console.error('error::::::::::::', e.message)
|
||||
})
|
||||
} catch (e) {
|
||||
setIsGlobalLoading(false)
|
||||
setIsBtnDisable(false);
|
||||
console.error('error::::::::::::', e.message)
|
||||
swalFire({ text: e.message, type: 'alert' , icon: 'error'})
|
||||
console.error('error::::::::::::', e.message)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
initQnaReg()
|
||||
},[])
|
||||
|
||||
// useEffect(() => {
|
||||
// onFileSave()
|
||||
//
|
||||
// }, [onFileSave])
|
||||
return (
|
||||
<div className="modal-popup">
|
||||
<div className="modal-dialog big">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h1 className="title">{getMessage('qna.title')}</h1>
|
||||
<button className="modal-close"
|
||||
onClick={() => {
|
||||
setOpen(false)
|
||||
}}>{getMessage('board.sub.btn.close')}</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="modal-body-inner">
|
||||
<div className="design-request-table">
|
||||
<div className="common-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style={{ width: '100px' }} />
|
||||
<col />
|
||||
<col style={{ width: '120px' }} />
|
||||
<col />
|
||||
<col style={{ width: '150px' }} />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{getMessage('qna.list.header.regNm')}</th>
|
||||
<td><input type="text" className="input-light" value={sessionState?.userNm || ''} readOnly /></td>
|
||||
<th>E-Mail<span className="red">*</span></th>
|
||||
<td ><input type="text" className="input-light" value={sessionState?.email || ''} readOnly /></td>
|
||||
<th>{getMessage('qna.reg.header.regDt')}</th>
|
||||
<td>{dayjs(new Date()).format('YYYY-MM-DD')}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{getMessage('qna.reg.header.regUserNm')}<span className="red">*</span></th>
|
||||
<td ><input type="text" className="input-light" required
|
||||
ref={regUserNmRef}
|
||||
value={qnaData?.regUserNm || '' }
|
||||
onChange={(e) => setQnaData({...qnaData, regUserNm: e.target.value })}
|
||||
onBlur={(e) => setQnaData({ ...qnaData, regUserNm: e.target.value })} /> </td>
|
||||
<th>{getMessage('qna.reg.header.regUserTelNo')}</th>
|
||||
<td colSpan={3}><input type="text" className="input-light"
|
||||
ref={regUserTelNoRef}
|
||||
maxLength={13}
|
||||
value={qnaData?.regUserTelNo || '' }
|
||||
onChange={regPhoneNumber}
|
||||
/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="design-request-grid">
|
||||
<div className="design-request-count">
|
||||
<div className="design-request-grid-tit">{getMessage("qna.reg.header.type")}, {getMessage("qna.reg.header.title")} <span
|
||||
className="red">*</span></div>
|
||||
</div>
|
||||
<div className="flx-box one-on-one">
|
||||
<div className="select-wrap mr5" >
|
||||
<Select name="" ref={qnaTypeLgCodeRef}
|
||||
options={qnaTypeLgCodeList}
|
||||
placeholder="Select"
|
||||
onChange={(e) => onChangeQnaTypeL(e)}
|
||||
getOptionLabel={(x) => x.clCodeNm}
|
||||
getOptionValue={(x) => x.clCode}
|
||||
isClearable={false}
|
||||
isSearchable={false}
|
||||
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div className="select-wrap mr5" >
|
||||
<Select name="" ref={qnaTypeMdCodeRef}
|
||||
options={qnaTypeMdCodeList}
|
||||
placeholder="Select"
|
||||
onChange={(e) => onChangeQnaTypeM(e)}
|
||||
getOptionLabel={(x) => x.clCodeNm}
|
||||
getOptionValue={(x) => x.clCode}
|
||||
isClearable={false}
|
||||
isSearchable={false}
|
||||
isDisabled={closeMdFlg}
|
||||
defaultValue={''}
|
||||
/>
|
||||
</div>
|
||||
<div className="select-wrap" >
|
||||
<Select name="" ref={qnaTypeSmCodeRef}
|
||||
options={qnaTypeSmCodeList}
|
||||
placeholder="Select"
|
||||
onChange={(e) => onChangeQnaTypeS(e)}
|
||||
getOptionLabel={(x) => x.clCodeNm}
|
||||
getOptionValue={(x) => x.clCode}
|
||||
isClearable={false}
|
||||
isSearchable={false}
|
||||
isDisabled={closeSmFlg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="input-wrap mt5">
|
||||
<input type="text" className="input-light" maxLength={200}
|
||||
ref = {titleRef}
|
||||
value={qnaData?.title || '' }
|
||||
onChange={(e) => {setQnaData({ ...qnaData, title: e.target.value })}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="design-request-grid mt15">
|
||||
<div className="design-request-count">
|
||||
<div className="design-request-grid-tit">{getMessage("qna.reg.header.contents")} <span className="red">*</span></div>
|
||||
</div>
|
||||
<div>
|
||||
<textarea className="textarea-form" name="" id="" maxLength={4000}
|
||||
ref={contentsRef}
|
||||
value={qnaData?.contents || '' }
|
||||
onChange={(e) => {setQnaData({ ...qnaData, contents: e.target.value })}} ></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<QnaFileUploader {...fileUploadProps} qnaData={qnaData} setQnaData={setQnaData} />
|
||||
|
||||
</div>
|
||||
<div className="footer-btn-wrap">
|
||||
{isBtnDisable === false && <button className="btn-origin grey mr5" onClick={handleQnaSubmit}>{getMessage("qna.reg.header.save")}</button>}
|
||||
<button className="btn-origin navy" onClick={() => {
|
||||
setOpen(false)
|
||||
}}>{getMessage("board.sub.btn.close")}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -142,6 +142,7 @@ export default function Header(props) {
|
||||
{ id: 7, name: 'header.menus.community.archive', url: '/community/archive', children: [] },
|
||||
],
|
||||
},
|
||||
{ id: 8, name: 'qna.title', url: '/community/qna', children: [] },
|
||||
]
|
||||
|
||||
const syncSession = useCallback(() => {
|
||||
@ -199,7 +200,7 @@ export default function Header(props) {
|
||||
onClick={() => {
|
||||
// moveHome()
|
||||
removeStuffRecoil(menu)
|
||||
if (pathName === '/') {
|
||||
if (pathName === '/' && menu.id !== 8) {
|
||||
window.location.reload()
|
||||
}
|
||||
}}
|
||||
|
||||
@ -1009,14 +1009,14 @@ export const usePolygon = () => {
|
||||
|
||||
// startPoint와 endPoint의 각도가 0,90,180,270이면 직선으로 판단
|
||||
if (Math.abs(startPoint.x - endPoint.x) < 2 || Math.abs(startPoint.y - endPoint.y) < 2) {
|
||||
if (!innerLine.attributes || !innerLine.attributes.type) {
|
||||
if (!innerLine.attributes || !innerLine.attributes.type || innerLine.attributes.type === 'default') {
|
||||
innerLine.attributes = {
|
||||
...innerLine.attributes,
|
||||
type: LINE_TYPE.SUBLINE.RIDGE,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!innerLine.attributes || !innerLine.attributes.type) {
|
||||
if (!innerLine.attributes || !innerLine.attributes.type || innerLine.attributes.type === 'default') {
|
||||
innerLine.attributes = {
|
||||
...innerLine.attributes,
|
||||
type: LINE_TYPE.SUBLINE.GABLE,
|
||||
@ -1149,7 +1149,7 @@ export const usePolygon = () => {
|
||||
|
||||
//allLines중 생성된 roof와 관련있는 line을 찾는다.
|
||||
|
||||
roof.lines = [...polygonLines, ...polygon.innerLines].filter((line) => {
|
||||
const roofLines = [...polygonLines, ...polygon.innerLines].filter((line) => {
|
||||
let startFlag = false
|
||||
let endFlag = false
|
||||
const startPoint = line.startPoint
|
||||
@ -1166,6 +1166,17 @@ export const usePolygon = () => {
|
||||
return startFlag && endFlag
|
||||
})
|
||||
|
||||
roofLines.forEach((line) => {
|
||||
roof.lines.forEach((roofLine) => {
|
||||
if (
|
||||
(isSamePoint(line.startPoint, roofLine.startPoint) && isSamePoint(line.endPoint, roofLine.endPoint)) ||
|
||||
(isSamePoint(line.startPoint, roofLine.endPoint) && isSamePoint(line.endPoint, roofLine.startPoint))
|
||||
) {
|
||||
roofLine.attributes = { ...line.attributes }
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
canvas.add(roof)
|
||||
// addLengthText(roof)
|
||||
canvas.remove(polygon)
|
||||
|
||||
@ -347,9 +347,9 @@
|
||||
"modal.actual.size.setting.not.exist.size": "実際の寸法の長さを入力してください",
|
||||
"modal.actual.size.setting.plane.size.length": "廊下寸法の長さ",
|
||||
"modal.actual.size.setting.actual.size.length": "実寸長",
|
||||
"plan.message.confirm.save": "プラン保存しますか?",
|
||||
"plan.message.confirm.copy": "プランコピーしますか?",
|
||||
"plan.message.confirm.delete": "プラン削除しますか?",
|
||||
"plan.message.confirm.save": "プラン保存しますか?",
|
||||
"plan.message.confirm.copy": "プランコピーしますか?",
|
||||
"plan.message.confirm.delete": "プラン削除しますか?",
|
||||
"plan.message.save": "保存されました。",
|
||||
"plan.message.delete": "削除されました。",
|
||||
"plan.message.leave": "物件状況(リスト)に移動しますか? [はい]を選択した場合は保存して移動します。",
|
||||
@ -597,6 +597,29 @@
|
||||
"board.sub.updDt": "更新",
|
||||
"board.sub.btn.close": "閉じる",
|
||||
"board.uptDt": "更新",
|
||||
"qna.sub.btn.inquiry": "お問い合わせ登録",
|
||||
"qna.title": "お問合せ",
|
||||
"qna.detail.sub.answer": "回答",
|
||||
"qna.detail.sub.fileList": "添付ファイル",
|
||||
"qna.sub.title": "お問合せリスト",
|
||||
"qna.reg.header.regDt": "お問い合わせ登録日",
|
||||
"qna.reg.header.regUserNm": "名前",
|
||||
"qna.reg.header.regUserTelNo": "お問い合わせ",
|
||||
"qna.reg.header.type": "お問い合わせ区分",
|
||||
"qna.reg.header.title": "お問い合わせタイトル",
|
||||
"qna.reg.header.contents": "お問い合わせ内容",
|
||||
"qna.reg.header.fileList": "ファイル添付",
|
||||
"qna.reg.header.save": "保存",
|
||||
"qna.reg.alert.require.regUserNm": "名前を入力してください。",
|
||||
"qna.reg.alert.select.type": "お問い合わせ区分を選択してください。",
|
||||
"qna.reg.alert.require.title": "タイトルを入力してください。",
|
||||
"qna.reg.alert.require.contents": "内容を入力してください。",
|
||||
"qna.reg.confirm.save": "1:1お問い合わせを登録しますか? <br/>Hanwha Japan 担当者にお問い合わせメールが送信されます。",
|
||||
"qna.reg.alert.save": "保存されました。",
|
||||
"qna.reg.alert.saveFail": "保存に失敗しました。",
|
||||
"qna.list.header.regNm": "登録者",
|
||||
"qna.list.header.answer.yes": "回答完了",
|
||||
"qna.list.header.answer.no": "未回答",
|
||||
"myinfo.title": "社員情報",
|
||||
"myinfo.info.userId": "ユーザーID",
|
||||
"myinfo.info.nameKana": "担当者名日本語",
|
||||
@ -1052,7 +1075,6 @@
|
||||
"module.not.found": "インストールモジュールを選択してください。",
|
||||
"module.circuit.minimun.error": "回路番号は1以上の数値を入力してください。",
|
||||
"module.already.exist.error": "回路番号が同じで異なるパワーコンディショナのモジュールがあります。 別の回路番号を設定してください。",
|
||||
"module.circuit.fix.not.same.roof.error": "異なる屋根面のモジュールが選択されています。 モジュールの選択をや直してください。",
|
||||
"construction.length.difference": "屋根面工法をすべて選択してください。",
|
||||
"menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。",
|
||||
"batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。",
|
||||
|
||||
@ -597,6 +597,29 @@
|
||||
"board.sub.updDt": "업데이트",
|
||||
"board.sub.btn.close": "닫기",
|
||||
"board.uptDt": "갱신",
|
||||
"qna.sub.btn.inquiry": "문의등록",
|
||||
"qna.title": "문의",
|
||||
"qna.sub.title": "문의 목록",
|
||||
"qna.detail.sub.answer": "답변",
|
||||
"qna.detail.sub.fileList": "첨부파일",
|
||||
"qna.reg.header.regDt": "문의등록일",
|
||||
"qna.reg.header.regUserNm": "이름",
|
||||
"qna.reg.header.regUserTelNo": "연락처",
|
||||
"qna.reg.header.type": "문의구분",
|
||||
"qna.reg.header.title": "문의제목",
|
||||
"qna.reg.header.contents": "문의정보",
|
||||
"qna.reg.header.fileList": "파일첨부",
|
||||
"qna.reg.header.save": "저장",
|
||||
"qna.reg.alert.require.regUserNm": "이름을 입력하세요.",
|
||||
"qna.reg.alert.select.type": "문의구분을 선택하세요.",
|
||||
"qna.reg.alert.require.title": "제목을 입력하세요.",
|
||||
"qna.reg.alert.require.contents": "내용을 입력하세요.",
|
||||
"qna.reg.confirm.save": "1:1문의를 등록하시겠습니까? <br/> Hanwha Japan 담당자에게 문의메일이 발송됩니다.",
|
||||
"qna.reg.alert.save": "저장 되었습니다.",
|
||||
"qna.reg.alert.saveFail": "저장에 실패하였습니다.",
|
||||
"qna.list.header.regNm": "등록자",
|
||||
"qna.list.header.answer.yes": "답변완료",
|
||||
"qna.list.header.answer.no": "미답변",
|
||||
"myinfo.title": "내정보",
|
||||
"myinfo.info.userId": "사용자ID",
|
||||
"myinfo.info.nameKana": "담당자명 일본어",
|
||||
|
||||
@ -151,6 +151,7 @@ button{
|
||||
.al-r{text-align: right !important;}
|
||||
.al-c{text-align: center !important;}
|
||||
|
||||
.org{color: #f86a56 !important;}
|
||||
|
||||
// button
|
||||
.btn-frame{
|
||||
|
||||
@ -388,6 +388,10 @@
|
||||
border: 1px solid #eee;
|
||||
.drag-file-area{
|
||||
margin-top: 0;
|
||||
.file-list {
|
||||
overflow-y: auto;
|
||||
max-height: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user