today_is

[ spring 프로젝트 ] 관리자 모드 - AJAX 이용 본문

project

[ spring 프로젝트 ] 관리자 모드 - AJAX 이용

ye_rang 2024. 3. 13. 15:45

관리자가  매장점주 회원가입을 승인/ 거부 할 수 있는 기능을 적용하기


 

 

관리자의 승인을 받으면, 매장점주의 데이터는 변동된다.

 

1) member 테이블에서 role이 2로 변경 (= 점주 회원의 기능을 사용가능함)

2) manager 테이블에서 status 가 1로 변경 (= 웹마스터의 승인을 의미함)

 

 

 

 변경한 내용 

: 버튼을 눌렀을때, 즉각적으로 변동되는 것이 맞다고 생각되어 AJAX 로 list를 띄우고, 클릭이벤트 처리했다

 

변경 전 변경 후

가입 대기 목록 list를 controller에서 @GetMapping으로 보여줌

(AJAX 사용 X)
AJAX사용해서 list 보여줌

 

 

 

변경 이유 (1)  

생각해보니 승인 / 거부 버튼을 눌렀을때의 변동사항이 페이지를 새로고침 해야만 나온다는 것을 알게 됐다

 

사용자 입장에서는 버튼을 눌렀을때 페이지 이동없이 즉각적으로 데이터가 변하는 것을 알아야하는데,

페이지를 새로 고침해야만 알 수 있는것이 불편할 것 같았다.

 


 

변경 이유 (2) 

승인과 거부 둘중에 한번만 눌러져야하는데, 둘다 누르는것이 가능하다 

 

차라리 list도  AJAX 를 사용하여, 페이지 이동없이도 즉각적인 데이터 변동이 보이도록 하는 것이 나을 듯하다.

 

 


 

 결과 

해당 list 는 manager 테이블에서 status 가 0 인 것들만 보여주는 것이기 때문에

승인 버튼을 누르면 status 가 1이 되거나,

거부 버튼을 누르면 delete 로 데이터가 아예 없어지기 때문에

사용자가 보이는 화면에서는 바로 목록에서 없어지는 것을 볼 수 있었다. 

 

 

거부버튼을 누르면 update가 아니라, 아예 데이터가 삭제되게 한 이유는

 

어차피 manager 테이블에서만 삭제될뿐이지

member 테이블에는 회원정보가 남아있기 때문이다 !!

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../header.jsp" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
	
	h2.ListCheckTitle {
		padding-top: 80px;
		padding-bottom: 30px;
	}
	p.ListCheckTitle {
		padding-bottom: 50px;
	}
	div.storeDetail {
		flex: 1;
		padding-bottom: 20px;
	}
	div.storeDetailData {
		flex: 5;
	}
	.paddingleft {
		padding-left: 50px;
	}
	.buttonPadding {
		padding-left: 150px;
	}
	.buttonTop {
		padding-top: 30px;
	}
	.storeMemberBorder {
		border: 1px solid grey;
		padding: 10px;
	}

</style>


</head>
<body>

	<div class="frame paddingleft">
		<h2 class="ListCheckTitle">매장점주 가입대기목록</h2>
		<p class="ListCheckTitle">매장점주의 가입을 승인 및 삭제할 수 있습니다.</p>
		
		<div id="root"></div>
	</div>
	
<script>

	
    
    function getHTMLfromJson(json) {
    	const cpath = '${cpath}'
		let tag = ''
		json.forEach(dto => {
			tag += `<div class="storeMemberBorder">`
			tag += `	<div class="flex">`
			tag += `		<div class="storeDetail">매장명</div><div class="storeDetailData">\${dto.store_name }</div>`
			tag += `	</div>`
			tag += `	<div class="flex">`
			tag += `		<div class="storeDetail">ID</div><div class="storeDetailData">\${dto.userid}</div>`
			tag += `	</div>`
			tag += `	<div class="flex">`
			tag += `		<div class="storeDetail">이름</div><div class="storeDetailData">\${dto.name}</div>`
			tag += `	</div>`
			tag += `	<div class="flex buttonTop">`
			tag += `		<div><button type="button" class="checkButton">승인</button>`
			tag += `			<input type="hidden" name="userid" value="\${dto.userid }" id="userid">`
			tag += `			<span id="result1"></span>`
			tag += `		</div>`
			tag += `		<div class="buttonPadding">`
			tag += `			<button type="button" class="deleteButton">거부</button>`
			tag += `			<input type="hidden" name="userid" value="\${dto.userid }" id="userid">`
			tag += `			<span id="result2"></span>`
			tag += `		</div>`
			tag += `	</div>`
			tag += `</div>`
		})	
		
		console.log(json)
		console.log(tag)
		return tag
	}

    async function loadHandler(){
    	const cpath = '${cpath}'
		const url = cpath + '/managerList'
		const json = await fetch(url).then(resp => resp.json())
		const tag = getHTMLfromJson(json)

		const root = document.querySelector('#root')
		root.innerHTML = tag
	    document.querySelector(".checkButton").addEventListener("click", checkButtonHandler)
	    document.querySelector(".deleteButton").addEventListener("click", deleteButtonHandler)
	}
    
    async function checkButtonHandler(){
    	const cpath = '${cpath}'
    	const userid = document.getElementById('userid').value
    	const url = cpath + '/storeMemberList?userid=' + userid
		const text = await fetch(url).then(resp => resp.text())
		document.getElementById("result1").innerText = text
		loadHandler()
    }

    async function deleteButtonHandler(){
    	const cpath = '${cpath}'
    	const userid = document.getElementById('userid').value
    	const url = cpath + '/deleteManager?userid=' + userid
		const text = await fetch(url).then(resp => resp.text())
		document.getElementById("result2").innerText = text
		loadHandler()
    }
    	

    window.addEventListener('DOMContentLoaded', loadHandler)
 
</script>

	
</body>
</html>

 

 

 


 

 DB 테이블 구조 

: 매장 점주는 웹 관리자를 통해서 "승인" 을 받아야만

매장 점주로서의 기능을 이용할 수 있도록 하기 위해서 manager 테이블을 만들었다.

create table member(
    idx         number          GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    userid      varchar2(500)   unique not null,
    userpw      varchar2(500)   not null,
    email       varchar2(500)   not null,
    nickname    varchar2(500)   unique not null,
    pnum        varchar2(500)   unique not null,
    role        number          check(role between 1 and 3) not null
        -- 1이면 전체관리자, 2이면 점주, 3이면 일반사용자
);


create table manager (
    idx         number          GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    userid      varchar2(500)    not null,
    name        varchar2(500)    not null,
    store_idx   number          not null,
    status      number          default 0 check(status in (0, 1)),
    -- 기본 '0' , 전체관리자가 확인하면 '1' -> 확인시 member의 role이 3에서 2로 바뀜
    
    constraint manager_member_fk
    foreign key (userid)
    references member(userid) on delete cascade,
    
    constraint manager_store_fk
    foreign key (store_idx)
    references store(idx) on delete cascade
);

 


느낀점

여러번 시도해보고 나서, 더 나은 방법으로 진행하게 되었다.

 

구현할 기능마다, 가장 최적의 방법이 있을 것이다.

 

 

처음부터 구현할 기능이 어떤 특징을 가져야할지 먼저 생각해본 다음에 기능을 구현하는 것이 좀 더 효율적일것이다.