사용자 목록 페이지 검색기능 추가.

thkim
강석 최 2024-01-15 16:18:06 +09:00
parent ebdecf4b62
commit 881f4fc080
7 changed files with 89 additions and 91 deletions

View File

@ -10,6 +10,16 @@ export function getQueryString(params){
return `?${Object.entries(params).map(e => e.join('=')).join('&') }` return `?${Object.entries(params).map(e => e.join('=')).join('&') }`
} }
export function convParams(params){
let str = "?"
for(let key in params){
if(params[key]){
str = str+key+"="+params[key]+"&";
}
}
return str;
}
export function requestFetch(url, requestOptions, handler, errorHandler) { export function requestFetch(url, requestOptions, handler, errorHandler) {
console.groupCollapsed("requestFetch"); console.groupCollapsed("requestFetch");
console.log("requestFetch [URL] : ", SERVER_URL + url); console.log("requestFetch [URL] : ", SERVER_URL + url);

View File

@ -2,7 +2,7 @@ import React, {useCallback, useEffect, useState} from "react";
import Form from "react-bootstrap/Form"; import Form from "react-bootstrap/Form";
import * as EgovNet from "api/egovFetch"; import * as EgovNet from "api/egovFetch";
function CheckBox({name, grpCd}){ function CheckBox({name, grpCd, selectedValue}){
const [checkBox, setCheckBox] = useState(); const [checkBox, setCheckBox] = useState();
@ -10,6 +10,15 @@ function CheckBox({name, grpCd}){
getCodeItemList() getCodeItemList()
}, []); }, []);
useEffect(() => {
if(selectedValue){
const itemCdAry = selectedValue.split(',');
itemCdAry.forEach(function(itemCd){
document.querySelector(`#chkBox_${itemCd}`).checked = true;
})
}
}, [selectedValue]);
function getCodeItemList() { function getCodeItemList() {
EgovNet.requestFetch( EgovNet.requestFetch(
'/commonCode/code-item?grpCd='+grpCd, '/commonCode/code-item?grpCd='+grpCd,
@ -25,8 +34,7 @@ function CheckBox({name, grpCd}){
id={`chkBox_${item.itemCd}`} id={`chkBox_${item.itemCd}`}
key={`chkBox_${item.itemCd}_${index}`} key={`chkBox_${item.itemCd}_${index}`}
name={name} name={name}
defaultValue={item.itemCd} value={item.itemCd}
onChange={()=>{}}
/> />
); );
}); });

View File

@ -5,10 +5,14 @@ import * as EgovNet from "api/egovFetch";
function SelectOption({name, grpCd, selectedValue}){ function SelectOption({name, grpCd, selectedValue}){
const [options, setOptions] = useState(); const [options, setOptions] = useState();
const [value, setValue] = useState(selectedValue)
useEffect(() => { useEffect(() => {
getCodeItemList() getCodeItemList()
}, []); }, []);
useEffect(() => {
setValue(selectedValue)
}, [selectedValue]);
function getCodeItemList(){ function getCodeItemList(){
EgovNet.requestFetch( EgovNet.requestFetch(
@ -33,7 +37,7 @@ function SelectOption({name, grpCd, selectedValue}){
} }
return ( return (
<Form.Select name={name} value={selectedValue} onChange={()=>{}}> <Form.Select name={name} value={value} onChange={(e)=>{setValue(e.target.value)}}>
{options} {options}
</Form.Select> </Form.Select>
) )

View File

@ -1,27 +1,27 @@
import React, {useCallback, useEffect, useRef, useState} from 'react'; import React, {useCallback, useEffect, useState} from 'react';
import {Link, useLocation} from "react-router-dom"; import {Link} from "react-router-dom";
import URL from "constants/url"; import URL from "constants/url";
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin'; import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
import EgovPaging from "components/EgovPaging"; import EgovPaging from "components/EgovPaging";
import * as EgovNet from "api/egovFetch"; import * as EgovNet from "api/egovFetch";
import {itemIdxByPage} from "utils/calc";
import Modal from "react-bootstrap/Modal"; import Modal from "react-bootstrap/Modal";
import UserInfoModal from "./UserInfoModal"; import UserInfoModal from "./UserInfoModal";
import CODE from "../../../constants/code"; import CODE from "../../../constants/code";
function List(props) { function List({}) {
const location = useLocation(); const [searchCondition, setSearchCondition] = useState({
pageIndex: 1,
userSe: '',
searchCondition: 'id',
searchKeyword: ''
});
const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || { pageIndex: 1, searchCnd: '0', searchWrd: '' });// ||
const [listTag, setListTag] = useState([]); const [listTag, setListTag] = useState([]);
const [paginationInfo, setPaginationInfo] = useState({}); const [paginationInfo, setPaginationInfo] = useState({});
const cndRef = useRef();
const wrdRef = useRef();
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
const [modalBody, setModalBody] = useState(); const [modalBody, setModalBody] = useState();
@ -29,7 +29,7 @@ function List(props) {
const handleShow = () => setShow(true); const handleShow = () => setShow(true);
const retrieveList = useCallback((searchCondition) => { const retrieveList = useCallback((searchCondition) => {
const params = "?"; const params = EgovNet.convParams(searchCondition);
EgovNet.requestFetch( EgovNet.requestFetch(
'/admin/users/list'+params, '/admin/users/list'+params,
{ {
@ -37,19 +37,11 @@ function List(props) {
}, },
(resp) => { (resp) => {
setPaginationInfo(resp.result.paginationInfo); setPaginationInfo(resp.result.paginationInfo);
let mutListTag = []; let mutListTag = [];
const resultCnt = parseInt(resp.result.contentCnt);
const currentPageNo = resp.result.paginationInfo.pageIndex;
const pageSize = resp.result.paginationInfo.rowCnt;
setListTag([]); setListTag([]);
// //
resp.result.userList.forEach(function (item, index) { resp.result.userList.forEach(function (item, index) {
const listIdx = itemIdxByPage(resultCnt , currentPageNo, pageSize, index);
mutListTag.push( mutListTag.push(
<div className={"list_item"} key={"userListDiv_"+index}> <div className={"list_item"} key={"userListDiv_"+index}>
<div>{item.userSe}</div> <div>{item.userSe}</div>
@ -75,12 +67,20 @@ function List(props) {
retrieveList(searchCondition); retrieveList(searchCondition);
}, []); }, []);
useEffect(() => {
retrieveList(searchCondition);
}, [searchCondition.pageIndex]);
const movePage = useCallback((passedPage) => {
setSearchCondition({...searchCondition, pageIndex: passedPage})
});
function userInfoModal(userSeq){ function userInfoModal(userSeq){
handleShow() handleShow()
setModalBody(<UserInfoModal userSeq={userSeq}></UserInfoModal>) setModalBody(<UserInfoModal userSeq={userSeq} reloadFunction={retrieveList}></UserInfoModal>)
} }
function removeUserInfo(seq){ const removeUserInfo = useCallback((seq)=>{
if(window.confirm("삭제하시겠습니까?\n복구할 수 없습니다.")){ if(window.confirm("삭제하시겠습니까?\n복구할 수 없습니다.")){
EgovNet.requestFetch( EgovNet.requestFetch(
'/admin/users/info', '/admin/users/info',
@ -94,13 +94,14 @@ function List(props) {
(resp) => { (resp) => {
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) { if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("삭제되었습니다.") alert("삭제되었습니다.")
retrieveList(searchCondition)
}else{ }else{
alert("삭제를 실패하였습니다.") alert("삭제를 실패하였습니다.")
} }
} }
) )
} }
} });
return ( return (
<div className="container"> <div className="container">
@ -128,18 +129,19 @@ function List(props) {
<ul> <ul>
<li className="third_1 L"> <li className="third_1 L">
<label className="f_select" htmlFor="sel1"> <label className="f_select" htmlFor="sel1">
<select id="sel1" title="조건" defaultValue={searchCondition.searchCnd} ref={cndRef}
onChange={e => {cndRef.current.value = e.target.value;}}> <select id="sel1" title="구분" defaultValue={searchCondition.userSe}
<option value="0">전체</option> onChange={(e) => {setSearchCondition({...searchCondition, userSe: e.target.value})}}>
<option value="1">일반사용자</option> <option value="">전체</option>
<option value="2">관리자</option> <option value="ACC_TP01">관리자</option>
<option value="ACC_TP02">일반사용자</option>
</select> </select>
</label> </label>
</li> </li>
<li className="third_1 L"> <li className="third_1 L">
<label className="f_select" htmlFor="sel1"> <label className="f_select" htmlFor="sel1">
<select id="sel1" title="조건" defaultValue={searchCondition.searchCnd} ref={cndRef} <select id="sel1" title="조건" defaultValue={searchCondition.searchCondition}
onChange={e => {cndRef.current.value = e.target.value;}}> onChange={(e) => {setSearchCondition({...searchCondition, searchCondition: e.target.value})}}>
<option value="id">아이디</option> <option value="id">아이디</option>
<option value="name">이름</option> <option value="name">이름</option>
<option value="email">이메일</option> <option value="email">이메일</option>
@ -149,15 +151,9 @@ function List(props) {
</li> </li>
<li className="third_2 R"> <li className="third_2 R">
<span className="f_search w_500"> <span className="f_search w_500">
<input type="text" name="" defaultValue={searchCondition.searchWrd} placeholder="" ref={wrdRef} <input type="text" name="" defaultValue={searchCondition.searchKeyword} placeholder=""
onChange={e => { onChange={(e) => {setSearchCondition({...searchCondition, searchKeyword: e.target.value})}}/>
wrdRef.current.value = e.target.value; <button type="button" onClick={() => {retrieveList(searchCondition)}}>조회</button>
}}
/>
<button type="button"
onClick={() => {
retrieveList({ ...searchCondition, pageIndex: 1, searchCnd: cndRef.current.value, searchWrd: wrdRef.current.value });
}}>조회</button>
</span> </span>
</li> </li>
</ul> </ul>
@ -179,15 +175,7 @@ function List(props) {
</div> </div>
<div className="board_bot"> <div className="board_bot">
<EgovPaging pagination={paginationInfo} <EgovPaging pagination={paginationInfo} moveToPage={passedPage => {movePage(passedPage)}} />
moveToPage={passedPage => {
retrieveList({
...searchCondition,
pageIndex: passedPage,
searchCnd: cndRef.current.value,
searchWrd: wrdRef.current.value
})
}} />
</div> </div>
</div> </div>
</div> </div>

View File

@ -9,7 +9,7 @@ import SelectOption from "components/commonCode/SelectOption";
import CheckBox from "components/commonCode/CheckBox"; import CheckBox from "components/commonCode/CheckBox";
import CODE from "../../../constants/code"; import CODE from "../../../constants/code";
function UserInfoModal({userSeq}){ function UserInfoModal({userSeq, reloadFunction}){
const [userInfo, setUserInfo] = useState({ userSeq: '', userId: '', password: '', passwordChk: '', userNm: '', email: '', phoneNum: '', userSe:'', userRole:'', status:''}); const [userInfo, setUserInfo] = useState({ userSeq: '', userId: '', password: '', passwordChk: '', userNm: '', email: '', phoneNum: '', userSe:'', userRole:'', status:''});
@ -78,6 +78,7 @@ function UserInfoModal({userSeq}){
(resp) => { (resp) => {
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) { if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("저장되었습니다.") alert("저장되었습니다.")
reloadFunction();
}else if(Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)){ }else if(Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)){
console.log("토큰 갱신중.") console.log("토큰 갱신중.")
}else{ }else{
@ -91,19 +92,6 @@ function UserInfoModal({userSeq}){
getModalContent(); getModalContent();
}, []); }, []);
useEffect(()=>{
const checkBoxDiv = document.querySelector("#ROLE_checkBoxDiv")
const userRole = userInfo.userRole;
if(userRole){
checkBoxDiv.childNodes.forEach(function (div){
const input = div.children[0];
if(userRole.includes(input.value)){
input.checked = true;
}
})
}
}, [userInfo]);
return ( return (
<> <>
<Modal.Header closeButton> <Modal.Header closeButton>
@ -175,7 +163,7 @@ function UserInfoModal({userSeq}){
사용자 권한 사용자 권한
</Form.Label> </Form.Label>
<Col sm={9}> <Col sm={9}>
<CheckBox name={"userRole"} grpCd={"ROLE"} /> <CheckBox name={"userRole"} grpCd={"ROLE"} selectedValue={userInfo?.userRole} />
</Col> </Col>
</Form.Group> </Form.Group>
<Form.Group as={Row} className="mb-3"> <Form.Group as={Row} className="mb-3">

View File

@ -85,37 +85,35 @@ public class AdminUsersController extends BaseController {
@RequestMapping(method = RequestMethod.PUT, value = "/info") @RequestMapping(method = RequestMethod.PUT, value = "/info")
public ResultVO modifyUserInfo(@RequestBody @Valid UserInfo info, Errors errors, @AuthenticationPrincipal LoginVO user) throws Exception{ public ResultVO modifyUserInfo(@RequestBody @Valid UserInfo info, Errors errors, @AuthenticationPrincipal LoginVO user) throws Exception{
ResultVO resultVO = new ResultVO(); ResultVO resultVO = new ResultVO();
Map<String, Object> resultMap = new HashMap<>();
if(errors.hasErrors()){ if(errors.hasErrors()){
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
for(FieldError error: errors.getFieldErrors()){ for(FieldError error: errors.getFieldErrors()){
msg.append(error.getDefaultMessage()); msg.append(error.getDefaultMessage());
msg.append("\n"); msg.append("\n");
} }
resultMap.put("resultCode", ResponseCode.INPUT_CHECK_ERROR.getCode()); resultVO.setResultCode(ResponseCode.INPUT_CHECK_ERROR.getCode());
resultMap.put("resultMessage", msg.toString()); resultVO.setResultMessage(msg.toString());
}else if(!info.getPassword().equals(info.getPasswordChk())){ }else if(!info.getPassword().equals(info.getPasswordChk())){
resultMap.put("resultCode", ResponseCode.SAVE_ERROR.getCode()); resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
resultMap.put("resultMessage", "비밀번호 확인이 잘못 입력되었습니다."); resultVO.setResultMessage("비밀번호 확인이 잘못 입력되었습니다.");
}else { }else {
Integer insertResult = adminUsersService.updateUserInfo(info, user.getId()); Integer insertResult = adminUsersService.updateUserInfo(info, user.getId());
if(insertResult!=null){ if(insertResult!=null){
if(insertResult==-1){ if(insertResult==-1){
resultMap.put("resultCode", ResponseCode.SAVE_ERROR.getCode()); resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
resultMap.put("resultMessage", "수정 대상이 존재하지 않습니다."); resultVO.setResultMessage("수정 대상이 존재하지 않습니다.");
}else if(insertResult==-2){ }else if(insertResult==-2){
resultMap.put("resultCode", ResponseCode.SAVE_ERROR.getCode()); resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
resultMap.put("resultMessage", "가입된 이메일입니다."); resultVO.setResultMessage("가입된 이메일입니다.");
}else{ }else{
resultMap.put("resultCode", ResponseCode.SUCCESS.getCode()); resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
resultMap.put("resultMessage", "저장 되었습니다."); resultVO.setResultMessage("저장 되었습니다.");
} }
}else{ }else{
resultMap.put("resultCode", ResponseCode.SAVE_ERROR.getCode()); resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
resultMap.put("resultMessage", "저장에 실패하였습니다."); resultVO.setResultMessage("저장에 실패하였습니다.");
} }
} }
resultVO.setResult(resultMap);
return resultVO; return resultVO;
} }
@ -129,7 +127,7 @@ public class AdminUsersController extends BaseController {
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님") @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
}) })
@RequestMapping(method = RequestMethod.DELETE, value = "/info", consumes = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(method = RequestMethod.DELETE, value = "/info", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResultVO deleteUserInfo(UserInfo info) throws Exception{ public ResultVO deleteUserInfo(@RequestBody UserInfo info) throws Exception{
ResultVO resultVO = new ResultVO(); ResultVO resultVO = new ResultVO();
adminUsersService.deleteUserInfo(info.getUserSeq()); adminUsersService.deleteUserInfo(info.getUserSeq());
resultVO.setResultCode(ResponseCode.SUCCESS.getCode()); resultVO.setResultCode(ResponseCode.SUCCESS.getCode());

View File

@ -31,17 +31,19 @@
<if test='userSe != null and userSe != ""'> <if test='userSe != null and userSe != ""'>
and user_se = #{userSe} and user_se = #{userSe}
</if> </if>
<if test='searchCondition == "id"'> <if test='searchKeyword != null and searchKeyword != ""'>
and user_id like '%'||#{searchKeyword}||'%' <if test='searchCondition == "id"'>
</if> and user_id like '%'||#{searchKeyword}||'%'
<if test='searchCondition == "name"'> </if>
and user_nm like '%'||#{searchKeyword}||'%' <if test='searchCondition == "name"'>
</if> and user_nm like '%'||#{searchKeyword}||'%'
<if test='searchCondition == "email"'> </if>
and email like '%'||#{searchKeyword}||'%' <if test='searchCondition == "email"'>
</if> and email like '%'||#{searchKeyword}||'%'
<if test='searchCondition == "phoneNum"'> </if>
and phone_num like '%'||#{searchKeyword}||'%' <if test='searchCondition == "phoneNum"'>
and phone_num like '%'||#{searchKeyword}||'%'
</if>
</if> </if>
</where> </where>
</sql> </sql>