+
+
+
-
)
}
diff --git a/src/components/auth/NewLogin.jsx b/src/components/auth/NewLogin.jsx
deleted file mode 100644
index 61c02abf..00000000
--- a/src/components/auth/NewLogin.jsx
+++ /dev/null
@@ -1,244 +0,0 @@
-'use client'
-
-import { useState, useRef, useEffect } from 'react'
-import Image from 'next/image'
-import Link from 'next/link'
-import { redirect } from 'next/navigation'
-import { useRecoilState } from 'recoil'
-import { useAxios } from '@/hooks/useAxios'
-import { setSession } from '@/lib/authActions'
-import { useMessage } from '@/hooks/useMessage'
-import { globalLocaleStore } from '@/store/localeAtom'
-import { sessionStore } from '@/store/commonAtom'
-import { modalContent, modalState } from '@/store/modalAtom'
-import '@/styles/style.scss'
-import { useRouter } from 'next/navigation'
-
-export default function NewLogin() {
- const [passwordVisible, setPasswordVisible] = useState(false)
- const passwordRef = useRef(null)
- const router = useRouter()
-
- useEffect(() => {
- setOpen(false)
- }, [])
-
- useEffect(() => {
- if (passwordVisible) {
- passwordRef.current.type = 'text'
- } else {
- passwordRef.current.type = 'password'
- }
- }, [passwordVisible])
-
- const { patch } = useAxios()
-
- const { getMessage } = useMessage()
- const [globalLocaleState, setGlbalLocaleState] = useRecoilState(globalLocaleStore)
- const [sessionState, setSessionState] = useRecoilState(sessionStore)
- const [isSelected, setIsSelected] = useState(globalLocaleState === 'ko' ? true : false)
-
- const handleSelected = () => {
- if (isSelected) {
- setGlbalLocaleState('ja')
- } else {
- setGlbalLocaleState('ko')
- }
-
- setIsSelected(!isSelected)
- }
-
- // login process
- const loginProcess = async (formData) => {
- const param = {
- // langCd: currentLocale
- langCd: globalLocaleState,
- lastEditUser: formData.get('id'),
- loginId: formData.get('id'),
- pwd: formData.get('password'),
- }
-
- // await post({ url: '/api/login/v1.0/login', data: param }).then((res) => {
- // if (res) {
- // if (res.result.resultCode == 'S') {
- // // console.log('res.data', res.data)
- // // 비밀번호 초기화가 필요한 경우
- // // if (res.data.pwdInitYn != 'Y') {
- // // alert('비밀번호 초기화가 필요한 경우')
- // // } else {
- // setSession(res.data)
- // redirect('/')
- // // }
- // } else {
- // alert(res.result.resultMsg)
- // }
- // }
- // })
-
- // 임시 로그인 처리
- setSession({
- userId: 'NEW016610',
- saleStoreId: null,
- name: null,
- mail: null,
- tel: null,
- storeId: 'TEMP02',
- userNm: 'ㅇㅇ6610',
- userNmKana: '신규사용자 16610',
- category: '인상6610',
- telNo: '336610',
- fax: null,
- email: 't10t@naver.com',
- pwdInitYn: 'Y',
- })
-
- setSessionState({
- userId: 'NEW016610',
- saleStoreId: null,
- name: null,
- mail: null,
- tel: null,
- storeId: 'TEMP02',
- userNm: 'ㅇㅇ6610',
- userNmKana: '신규사용자 16610',
- category: '인상6610',
- telNo: '336610',
- fax: null,
- email: 't10t@naver.com',
- pwdInitYn: 'Y',
- })
-
- // redirect('/')
- router.push('/')
- // 임시 로그인 처리 끝
- }
-
- // 비밀번호 초기화 관련
- const [open, setOpen] = useRecoilState(modalState)
- const [contents, setContent] = useRecoilState(modalContent)
-
- const initPasswordProcess = async (formData) => {
- const param = {
- langCd: currentLocale,
- lastEditUser: formData.get('checkId'),
- loginId: formData.get('checkId'),
- email: formData.get('checkEmail'),
- }
-
- await patch({ url: '/api/login/v1.0/user/init-password', data: param }).then((res) => {
- if (res) {
- if (res.result.resultCode == 'S') {
- alert(getMessage('login.init_password.complete_message'))
- redirect('/login')
- } else {
- alert(res.result.resultMsg)
- }
- }
- })
- }
-
- const initPasswordContent = (
-
-
-
- )
-
- return (
-
-
-
-
-
-
-
- ※当サイトをご利用の際は、事前申請が必要です。
-
- IDがない方は ID申請 クリックしてください。
-
-
-
COPYRIGHT©2024 Hanwha Japan All Rights Reserved.
-
- )
-}
diff --git a/src/components/community/Archive.jsx b/src/components/community/Archive.jsx
index dcfc737f..768bc500 100644
--- a/src/components/community/Archive.jsx
+++ b/src/components/community/Archive.jsx
@@ -1,7 +1,71 @@
+'use client'
+
+import Link from 'next/link'
+import Image from 'next/image'
+
+import Search from '@/components/community/Search'
+import ArchiveTable from '@/components/community/ArchiveTable'
+
+import { useEffect, useState } from 'react'
+import { useResetRecoilState } from 'recoil'
+import { useMessage } from '@/hooks/useMessage'
+
+import { searchState } from '@/store/boardAtom'
+
export default function Archive() {
+ const { getMessage } = useMessage()
+ const resetSearch = useResetRecoilState(searchState)
+ const [isInitialized, setIsInitialized] = useState(false)
+
+ useEffect(() => {
+ resetSearch()
+ setIsInitialized(true)
+ }, [])
+
+ if (!isInitialized) {
+ return null
+ }
+
+ const boardType = {
+ boardTitle: getMessage('board.archive.title'),
+ subTitle: getMessage('board.archive.sub.title'),
+ clsCode: 'DOWN',
+ }
+
return (
<>
-
Community Archive
+
+
+
+ -
+
+ {getMessage('board.archive.title')}
+
+
+
+
+ -
+
+
+
+
+ -
+ {getMessage('header.menus.community')}
+
+ -
+ {getMessage('board.archive.title')}
+
+
+
+
+
>
)
}
diff --git a/src/components/community/ArchiveTable.jsx b/src/components/community/ArchiveTable.jsx
new file mode 100644
index 00000000..318badef
--- /dev/null
+++ b/src/components/community/ArchiveTable.jsx
@@ -0,0 +1,103 @@
+'use client'
+
+import { useEffect, useState } from 'react'
+import { useRecoilState } from 'recoil'
+import { useAxios } from '@/hooks/useAxios'
+
+import { searchState } from '@/store/boardAtom'
+import { useMessage } from '@/hooks/useMessage'
+
+import { handleFileDown } from '@/util/board-utils'
+
+export default function ArchiveTable({ clsCode }) {
+ const { getMessage } = useMessage()
+
+ // api 조회 관련
+ const { get } = useAxios()
+ const [search, setSearch] = useRecoilState(searchState)
+ const [boardList, setBoardList] = useState([])
+
+ // 목록 조회
+ useEffect(() => {
+ async function fetchData() {
+ const url = `${process.env.NEXT_PUBLIC_API_SERVER_PATH}/api/board/list`
+ const params = new URLSearchParams({
+ schNoticeTpCd: 'QC',
+ schNoticeClsCd: clsCode,
+ schTitle: search.searchValue ? search.searchValue : '',
+ })
+ const apiUrl = `${url}?${params.toString()}`
+
+ const resultData = await get({ url: apiUrl })
+
+ if (resultData) {
+ if (resultData.result.code === 200) {
+ setBoardList(resultData.data)
+ if (resultData.data.length > 0) {
+ setSearch({ ...search, totalCount: resultData.data[0].totCnt })
+ } else {
+ setSearch({ ...search, totalCount: 0 })
+ }
+ } else {
+ alert(resultData.result.message)
+ }
+ }
+ }
+
+ fetchData()
+ }, [search.searchValue])
+
+ // 상세 파일 목록 조회
+ const handleDetailFileListDown = async (noticeNo) => {
+ const url = `${process.env.NEXT_PUBLIC_API_SERVER_PATH}/api/board/detail`
+ const params = new URLSearchParams({
+ noticeNo: noticeNo,
+ })
+ const apiUrl = `${url}?${params.toString()}`
+
+ const resultData = await get({ url: apiUrl })
+
+ if (resultData) {
+ if (resultData.result.code === 200) {
+ const boardDetailFileList = resultData.data.listFile
+
+ if (boardDetailFileList && Array.isArray(boardDetailFileList)) {
+ boardDetailFileList.forEach((boardFile) => {
+ handleFileDown(boardFile)
+ })
+ }
+ } else {
+ alert(resultData.result.message)
+ }
+ }
+ }
+
+ return (
+ <>
+
+ {boardList?.map((board) => (
+
+
+
+ {/* 번호 */}
+ {board.rowNumber}
+
+
+ {/* 제목 */}
+ {board.title}
+
+
+ {/* 등록일 */}
+ {getMessage('board.sub.updDt')} : {board.uptDt ? board.uptDt : board.regDt}
+
+
+
+ {/* 첨부파일 */}
+
+
+
+ ))}
+
+ >
+ )
+}
diff --git a/src/components/community/Faq.jsx b/src/components/community/Faq.jsx
index 722741b3..17254f5c 100644
--- a/src/components/community/Faq.jsx
+++ b/src/components/community/Faq.jsx
@@ -1,7 +1,80 @@
+'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 Table from '@/components/community/Table'
+
+import { useEffect, useState } from 'react'
+import { useResetRecoilState, useRecoilValue, useRecoilState } from 'recoil'
+import { useMessage } from '@/hooks/useMessage'
+
+import { searchState } from '@/store/boardAtom'
+
export default function Faq() {
+ const { getMessage } = useMessage()
+ const resetSearch = useResetRecoilState(searchState)
+ const [isInitialized, setIsInitialized] = useState(false)
+
+ const search = useRecoilValue(searchState)
+ const [searchForm, setSearchForm] = useRecoilState(searchState)
+
+ useEffect(() => {
+ if (search.mainFlag === 'N') {
+ resetSearch()
+ } else {
+ setSearchForm({ ...searchForm, mainFlag: 'N' })
+ }
+ setIsInitialized(true)
+ }, [])
+
+ if (!isInitialized) {
+ return null
+ }
+
+ const boardType = {
+ boardTitle: getMessage('board.faq.title'),
+ subTitle: getMessage('board.faq.sub.title'),
+ clsCode: 'FAQ',
+ }
+
return (
<>
-
Community FAQ
+
+
+
+ -
+
+ {getMessage('board.faq.title')}
+
+
+
+
+ -
+
+
+
+
+ -
+ {getMessage('header.menus.community')}
+
+ -
+ {getMessage('board.faq.title')}
+
+
+
+
+
>
)
}
diff --git a/src/components/community/Notice.jsx b/src/components/community/Notice.jsx
index 2ab67c8e..55dfbad1 100644
--- a/src/components/community/Notice.jsx
+++ b/src/components/community/Notice.jsx
@@ -1,7 +1,72 @@
+'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 Table from '@/components/community/Table'
+
+import { useEffect, useState } from 'react'
+import { useResetRecoilState } from 'recoil'
+import { useMessage } from '@/hooks/useMessage'
+
+import { searchState } from '@/store/boardAtom'
+
export default function Notice() {
+ const { getMessage } = useMessage()
+ const resetSearch = useResetRecoilState(searchState)
+ const [isInitialized, setIsInitialized] = useState(false)
+
+ useEffect(() => {
+ resetSearch()
+ setIsInitialized(true)
+ }, [])
+
+ if (!isInitialized) {
+ return null
+ }
+
+ const boardType = {
+ boardTitle: getMessage('board.notice.title'),
+ subTitle: getMessage('board.notice.sub.title'),
+ clsCode: 'NOTICE',
+ }
return (
<>
-
Community Notice
+
+
+
+ -
+
+ {getMessage('board.notice.title')}
+
+
+
+
+ -
+
+
+
+
+ -
+ {getMessage('header.menus.community')}
+
+ -
+ {getMessage('board.notice.title')}
+
+
+
+
+
>
)
}
diff --git a/src/components/community/Pagination.jsx b/src/components/community/Pagination.jsx
new file mode 100644
index 00000000..938f5b0d
--- /dev/null
+++ b/src/components/community/Pagination.jsx
@@ -0,0 +1,78 @@
+'use client'
+
+import { searchState } from '@/store/boardAtom'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { generateBlockPagination } from '@/util/board-utils'
+
+export default function Pagination() {
+ const search = useRecoilValue(searchState)
+
+ const [searchForm, setSearchForm] = useRecoilState(searchState)
+
+ const handlePagination = (pageNum) => {
+ setSearchForm({ ...searchForm, currentPage: pageNum })
+ }
+
+ const totalPages = Math.ceil(search.totalCount / search.pageBlock) > 0 ? Math.ceil(search.totalCount / search.pageBlock) : 1
+ const allPages = generateBlockPagination(search.currentPage, totalPages, 10)
+
+ return (
+ <>
+
+ -
+
+
+ -
+
+
+
+ {/* 페이지목록 */}
+ {allPages.map((page, index) => {
+ return (
+ -
+
+
+ )
+ })}
+
+ -
+
+
+ -
+
+
+
+ >
+ )
+}
diff --git a/src/components/community/Search.jsx b/src/components/community/Search.jsx
new file mode 100644
index 00000000..26ca1883
--- /dev/null
+++ b/src/components/community/Search.jsx
@@ -0,0 +1,117 @@
+'use client'
+
+import { searchState } from '@/store/boardAtom'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { useState } from 'react'
+import { useMessage } from '@/hooks/useMessage'
+
+export default function Search({ title = '', subTitle = '', isSelectUse = false }) {
+ const { getMessage } = useMessage()
+
+ const search = useRecoilValue(searchState)
+ const [searchForm, setSearchForm] = useRecoilState(searchState)
+
+ const [selectPageBlock, setSelectPageBlock] = useState(search.pageBlock)
+ const [searchValue, setSearchValue] = useState(search.searchValue)
+ const [searchView, setSearchView] = useState(search.searchValue ? true : false)
+ const [searchViewText, setSearchViewText] = useState(search.searchValue ? search.searchValue : '')
+
+ // Enter 키 처리
+ const handleKeyDown = (e) => {
+ if (e.key === 'Enter') {
+ handleSubmit(e)
+ }
+ }
+
+ // 조회 값 처리
+ const handleSearch = (text, block) => {
+ if (text !== '') {
+ setSearchView(true)
+ setSearchViewText(text)
+ setSearchForm({ ...searchForm, currentPage: 1, searchValue: text, pageBlock: block, searchFlag: true })
+ } else {
+ setSearchView(false)
+ setSearchViewText('')
+ setSearchForm({ ...searchForm, currentPage: 1, searchValue: '', pageBlock: block, searchFlag: !searchForm.searchFlag })
+ }
+ // 조회 후 값 비워주기
+ setSearchValue('')
+ }
+
+ const handleSubmit = (e) => {
+ e.preventDefault()
+ handleSearch(searchValue, selectPageBlock)
+ }
+
+ return (
+ <>
+
+
+ {
+ setSearchValue(e.target.value)
+ }}
+ onKeyDown={handleKeyDown}
+ value={searchValue}
+ />
+
+
+ {searchView && (
+
+ {isSelectUse ? (
+ <>
+
${searchViewText}`, `${search.totalCount}`]),
+ }}
+ >
+ >
+ ) : (
+ <>
+
${searchViewText}`, `${search.totalCount}`]),
+ }}
+ >
+ >
+ )}
+
+ )}
+
+
+
+
{subTitle}
+
+ -
+ {getMessage('board.sub.total')} {search.totalCount}
+
+
+
+ {isSelectUse && (
+
+
+
+
+
+ )}
+
+ >
+ )
+}
diff --git a/src/components/community/Table.jsx b/src/components/community/Table.jsx
new file mode 100644
index 00000000..f943bc86
--- /dev/null
+++ b/src/components/community/Table.jsx
@@ -0,0 +1,110 @@
+'use client'
+
+import { useEffect, useState } from 'react'
+import { useRecoilState } from 'recoil'
+
+import { searchState } from '@/store/boardAtom'
+
+import { useAxios } from '@/hooks/useAxios'
+import { useMessage } from '@/hooks/useMessage'
+
+import BoardDetailModal from '../community/modal/BoardDetailModal'
+
+export default function Table({ clsCode }) {
+ const { getMessage } = useMessage()
+
+ // api 조회 관련
+ const { get } = useAxios()
+ const [search, setSearch] = useRecoilState(searchState)
+ const [boardList, setBoardList] = useState([])
+
+ // 팝업 관련
+ const [open, setOpen] = useState(false)
+ const [modalNoticeNo, setModalNoticeNo] = useState('')
+
+ // 목록 조회
+ useEffect(() => {
+ async function fetchData() {
+ 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: clsCode,
+ schTitle: search.searchValue ? search.searchValue : '',
+ startRow: startRow,
+ endRow: endRow,
+ })
+ 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)
+ }
+ }
+ }
+
+ fetchData()
+ }, [search.currentPage, search.searchValue, search.pageBlock, search.searchFlag])
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+ {boardList.length > 0 ? (
+ boardList?.map((board) => (
+ {
+ setOpen(true)
+ setModalNoticeNo(board.noticeNo)
+ }}
+ >
+ |
+ {/* 번호 */}
+ {board.rowNumber}
+ |
+
+ {/* 제목 */}
+
+ {board.title}
+ {board.attachYn && }
+
+ |
+
+ {/* 등록일 */}
+ {board.regDt.split(' ')[0]}
+ |
+
+ ))
+ ) : (
+
+ |
+ {getMessage('common.message.no.data')}
+ |
+
+ )}
+
+
+
+ {open &&
}
+ >
+ )
+}
diff --git a/src/components/community/modal/BoardDetailModal.jsx b/src/components/community/modal/BoardDetailModal.jsx
new file mode 100644
index 00000000..dec5e09a
--- /dev/null
+++ b/src/components/community/modal/BoardDetailModal.jsx
@@ -0,0 +1,77 @@
+'use client'
+
+import { useEffect, useState } from 'react'
+import { useAxios } from '@/hooks/useAxios'
+import { handleFileDown } from '@/util/board-utils'
+
+export default function BoardDetailModal({ noticeNo, setOpen }) {
+ // api 조회 관련
+ const { get } = useAxios()
+ const [boardDetail, setBoardDetail] = useState({})
+
+ useEffect(() => {
+ // 상세 조회
+ const fetchDetail = async (noticeNo) => {
+ const url = `/api/board/detail`
+ const params = new URLSearchParams({
+ noticeNo: noticeNo,
+ })
+ 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(noticeNo)
+ }, [])
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
{boardDetail.title}
+
+ {boardDetail.listFile && (
+
+ - 첨부파일 목록
+ {boardDetail.listFile.map((boardFile) => (
+ -
+
+
+ ))}
+
+ )}
+
+
{boardDetail.contents}
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx
index 65da6051..c9b89658 100644
--- a/src/components/header/Header.jsx
+++ b/src/components/header/Header.jsx
@@ -12,6 +12,8 @@ import { logout } from '@/lib/authActions'
import QSelectBox from '@/components/common/select/QSelectBox'
+import UserInfoModal from '@/components/myInfo/UserInfoModal'
+
export const ToggleonMouse = (e, act, target) => {
const listWrap = e.target.closest(target)
const ListItem = Array.from(listWrap.childNodes)
@@ -28,6 +30,8 @@ export const ToggleonMouse = (e, act, target) => {
}
export default function Header(props) {
+ const [userInfoModal, setUserInfoModal] = useState(false)
+
const { userSession } = props
const [sessionState, setSessionState] = useRecoilState(sessionStore)
const { getMessage } = useMessage()
@@ -137,9 +141,15 @@ export default function Header(props) {