마이페이지 개인정보 수정, 연동 기능 추가.

강석 최 2022-10-31 18:23:22 +09:00
parent ac9978fd0f
commit 0e417796ae
8 changed files with 296 additions and 98 deletions

View File

@ -1,5 +1,7 @@
package com.dbnt.faisp.main.userInfo; package com.dbnt.faisp.main.userInfo;
import com.dbnt.faisp.kwms.service.KwmsService;
import com.dbnt.faisp.main.codeMgt.service.CodeMgtService;
import com.dbnt.faisp.main.userInfo.model.DashboardConfig; import com.dbnt.faisp.main.userInfo.model.DashboardConfig;
import com.dbnt.faisp.main.userInfo.model.UserInfo; import com.dbnt.faisp.main.userInfo.model.UserInfo;
import com.dbnt.faisp.main.userInfo.service.UserInfoService; import com.dbnt.faisp.main.userInfo.service.UserInfoService;
@ -16,11 +18,21 @@ import java.util.List;
public class MyInfoController { public class MyInfoController {
private final UserInfoService userInfoService; private final UserInfoService userInfoService;
private final CodeMgtService codeMgtService;
private final KwmsService kwmsService;
@GetMapping("/myInfoPage") @GetMapping("/myInfoPage")
public ModelAndView myInfoPage(@AuthenticationPrincipal UserInfo loginUser){ public ModelAndView myInfoPage(@AuthenticationPrincipal UserInfo loginUser){
ModelAndView mav = new ModelAndView("user/myInfo"); ModelAndView mav = new ModelAndView("user/myInfo");
mav.addObject("userInfo", loginUser); mav.addObject("userInfo", userInfoService.selectUserInfo(loginUser.getUserSeq()));
mav.addObject("ogList", codeMgtService.selectCodeMgtList("OG"));
mav.addObject("ofcList", codeMgtService.selectCodeMgtList("OFC"));
mav.addObject("titleList", codeMgtService.selectCodeMgtList("JT"));
mav.addObject("outturnList", codeMgtService.selectCodeMgtList("OTC"));
mav.addObject("seriesList", codeMgtService.selectCodeMgtList("SRC"));
mav.addObject("languageList", codeMgtService.selectCodeMgtList("LNG"));
mav.addObject("statusList", codeMgtService.selectCodeMgtList("USC"));
mav.addObject("dashboardConfigList", userInfoService.getDashboardConfigList(loginUser.getUserSeq())); mav.addObject("dashboardConfigList", userInfoService.getDashboardConfigList(loginUser.getUserSeq()));
return mav; return mav;
} }
@ -44,4 +56,18 @@ public class MyInfoController {
userInfoService.saveDashboardConfigList(loginUser.getUserSeq(), configList); userInfoService.saveDashboardConfigList(loginUser.getUserSeq(), configList);
} }
@PostMapping("/updateSelf")
public void updateSelf(@AuthenticationPrincipal UserInfo loginUser, UserInfo userInfo) {
userInfo.setUserSeq(loginUser.getUserSeq());
userInfoService.updateUserInfo(userInfo);
}
@PostMapping("/syncSelfToKwms")
public void syncSelfToKwms(@AuthenticationPrincipal UserInfo loginUser, UserInfo userInfo) {
UserInfo kwmsInfo = kwmsService.selectEmpInfo(userInfo.getDicCode());
if(kwmsInfo!= null){
kwmsInfo.setUserSeq(loginUser.getUserSeq());
userInfoService.updateUserInfo(kwmsInfo);
}
}
} }

View File

@ -42,6 +42,9 @@ public class UserInfoService implements UserDetailsService {
public void updateUserInfo(UserInfo userInfo){ public void updateUserInfo(UserInfo userInfo){
UserInfo savedInfo = userInfoRepository.findById(userInfo.getUserSeq()).orElse(null); UserInfo savedInfo = userInfoRepository.findById(userInfo.getUserSeq()).orElse(null);
if(savedInfo!=null){ if(savedInfo!=null){
if(userInfo.getDicCode()!=null){
savedInfo.setDicCode(userInfo.getDicCode());
}
if(userInfo.getUserNm()!=null){ if(userInfo.getUserNm()!=null){
savedInfo.setUserNm(userInfo.getUserNm()); savedInfo.setUserNm(userInfo.getUserNm());
} }

View File

@ -84,6 +84,10 @@ public class userMgtController {
userInfoService.updateUserInfo(kwmsInfo); userInfoService.updateUserInfo(kwmsInfo);
} }
} }
return ""; if(infoList.size()==1){
return infoList.get(0).getUserSeq().toString();
}else{
return "";
}
} }
} }

View File

@ -1,6 +1,11 @@
let selectedList = []; let selectedList = [];
$(function (){ $(function (){
$(".dateSelector").datepicker({
format: "yyyy-mm-dd",
language: "ko",
autoclose: true
});
$.ajax({ $.ajax({
type : 'GET', type : 'GET',
url : "/myInfo/getDashBoardConfig", url : "/myInfo/getDashBoardConfig",
@ -13,7 +18,50 @@ $(function (){
} }
}) })
}) })
$(document).on('click', '#updateBtn', function (){
if(confirm("저장하시겠습니까?")){
contentFade("in");
const formData = new FormData($("#userInfoUpdate")[0]);
$.ajax({
type : 'POST',
data : formData,
url : "/myInfo/updateSelf",
processData: false,
contentType: false,
success : function() {
alert("저장되었습니다.");
contentFade("out");
location.reload();
},
error : function(xhr, status) {
alert("저장에 실패하였습니다.");
contentFade("out");
}
})
}
})
$(document).on('click', '#syncBtn', function (){
if(confirm("연동하시겠습니까?")){
contentFade("in");
$.ajax({
type : 'POST',
url : "/myInfo/syncSelfToKwms",
data : {dicCode: $("#dicCode").val()},
beforeSend: function (xhr){
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
},
success : function(data) {
alert("갱신 되었습니다.");
contentFade("out");
location.reload();
},
error : function(xhr, status) {
alert("갱신에 실패하였습니다");
contentFade("out");
}
})
}
})
$(document).on('click', '.configTr', function (event){ $(document).on('click', '.configTr', function (event){
const target = event.target; const target = event.target;
if(!(target.className === "moveTd" || $(target).parents(".moveTd").length>0)){ if(!(target.className === "moveTd" || $(target).parents(".moveTd").length>0)){

View File

@ -8,24 +8,7 @@ $(document).on('click', '#stayTab', function (){
$(document).on('click', '.userInfoTr', function (event){ $(document).on('click', '.userInfoTr', function (event){
if(!event.target.className.includes("heckBox")){ if(!event.target.className.includes("heckBox")){
$.ajax({ openEditModal($(this).find(".userSeq").val())
url: '/userMgt/userEditModal',
data: {userSeq: Number($(this).find(".userSeq").val())},
type: 'GET',
dataType:"html",
success: function(html){
$("#userEditModalContent").empty().append(html)
$(".dateSelector").datepicker({
format: "yyyy-mm-dd",
language: "ko",
autoclose: true
});
$("#userEditModal").modal('show');
},
error:function(){
}
});
} }
}) })
@ -56,7 +39,6 @@ $(document).on('click', '#updateBtn', function (){
$(document).on('click', '#deleteBtn', function (){ $(document).on('click', '#deleteBtn', function (){
if(confirm("삭제 하시겠습니까?")){ if(confirm("삭제 하시겠습니까?")){
console.log($("#userSeq").val());
deleteUser([{userSeq: Number($("#userSeq").val())}]) deleteUser([{userSeq: Number($("#userSeq").val())}])
} }
}) })
@ -110,6 +92,9 @@ function syncUserInfoToKwms(userList){
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val()); xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
}, },
success : function(data) { success : function(data) {
if(userList.length===1){
openEditModal(userList[0].userSeq);
}
alert("갱신 되었습니다."); alert("갱신 되었습니다.");
}, },
error : function(xhr, status) { error : function(xhr, status) {
@ -197,4 +182,23 @@ function deleteUser(userList){
}) })
} }
function openEditModal(userSeq){
$.ajax({
url: '/userMgt/userEditModal',
data: {userSeq: Number(userSeq)},
type: 'GET',
dataType:"html",
success: function(html){
$("#userEditModalContent").empty().append(html)
$(".dateSelector").datepicker({
format: "yyyy-mm-dd",
language: "ko",
autoclose: true
});
$("#userEditModal").modal('show');
},
error:function(){
}
});
}

View File

@ -5,7 +5,7 @@
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form id="userInfoUpdate" action="#" th:action="@{/admin/insertUserInfo}" method="post"> <form id="userInfoUpdate" action="#" method="post">
<input type="hidden" name="userSeq" id="userSeq" class="userSeq" th:value="${userInfo.userSeq}"> <input type="hidden" name="userSeq" id="userSeq" class="userSeq" th:value="${userInfo.userSeq}">
<input type="hidden" name="userStatus" th:value="${userInfo.userStatus}"> <input type="hidden" name="userStatus" th:value="${userInfo.userStatus}">
<div class="mb-3 mt-3 row"> <div class="mb-3 mt-3 row">
@ -32,7 +32,7 @@
<label for="userId" class="col-sm-2 col-form-label col-form-label-sm text-center ">아이디</label> <label for="userId" class="col-sm-2 col-form-label col-form-label-sm text-center ">아이디</label>
<div class="col-sm-4"> <div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="userId" name="userId" autocomplete="off" th:value="${userInfo.userId}" readonly> <input type="text" class="form-control form-control-sm" id="userId" name="userId" autocomplete="off" th:value="${userInfo.userId}" readonly>
<label for="userId" style="font-size: 12px">6~20자 사이의 알파벳, 숫자를 입력하세요</label> <label for="userId" style="font-size: 12px">아이디는 수정할 수 없습니다.</label>
</div> </div>
<label for="userNm" class="col-sm-2 col-form-label col-form-label-sm text-center">이름</label> <label for="userNm" class="col-sm-2 col-form-label col-form-label-sm text-center">이름</label>
<div class="col-sm-4"> <div class="col-sm-4">

View File

@ -1,39 +1,39 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org"> <html lang="ko" xmlns:th="http://www.thymeleaf.org">
<div class="mx-3 pt-3" th:fragment="leftMenuFragment"> <div class="mx-3 pt-3" th:fragment="leftMenuFragment">
<a href="/" class="d-flex"> <a href="/" class="d-flex">
<img id="logo" th:src="@{/img/logo.png}" alt="logo" title="logo"> <img id="logo" th:src="@{/img/logo.png}" alt="logo" title="logo">
</a> </a>
<ul class="nav nav-pills flex-column my-3"> <ul class="nav nav-pills flex-column my-3">
<li th:each="firstMenu:${session.menuList}"> <li th:each="firstMenu:${session.menuList}">
<th:block th:each="cat1Code:${session.commonCode.get('CAT1')}"> <th:block th:each="cat1Code:${session.commonCode.get('CAT1')}">
<th:block th:if="${cat1Code.itemCd eq firstMenu.cat1Cd}"> <th:block th:if="${cat1Code.itemCd eq firstMenu.cat1Cd}">
<a href="#" class="nav-link link-dark firstMenuLink" th:text="${cat1Code.itemValue}"></a> <a href="#" class="nav-link link-dark firstMenuLink" th:text="${cat1Code.itemValue}"></a>
<div class="menuDiv secondMenu h-100 bg-white" style="display: none"> <div class="menuDiv secondMenu h-100 bg-white" style="display: none">
<ul class="nav nav-pills flex-column"> <ul class="nav nav-pills flex-column">
<li th:each="secondMenu:${firstMenu.childList}"> <li th:each="secondMenu:${firstMenu.childList}">
<th:block th:each="cat2Code:${session.commonCode.get('CAT2')}"> <th:block th:each="cat2Code:${session.commonCode.get('CAT2')}">
<th:block th:if="${cat2Code.itemCd eq secondMenu.cat2Cd}"> <th:block th:if="${cat2Code.itemCd eq secondMenu.cat2Cd}">
<a class="nav-link link-dark secondMenuLink" th:text="${cat2Code.itemValue}" th:href="${#lists.isEmpty(secondMenu.childList)?secondMenu.menuUrl:'#'}"></a> <a class="nav-link link-dark secondMenuLink" th:text="${cat2Code.itemValue}" th:href="${#lists.isEmpty(secondMenu.childList)?secondMenu.menuUrl:'#'}"></a>
<div class="menuDiv thirdMenu h-100 bg-white" style="display: none" th:if="${#lists.isEmpty(secondMenu.childList) ne true}"> <div class="menuDiv thirdMenu h-100 bg-white" style="display: none" th:if="${#lists.isEmpty(secondMenu.childList) ne true}">
<ul class="nav nav-pills flex-column"> <ul class="nav nav-pills flex-column">
<li th:each="thirdMenu:${secondMenu.childList}"> <li th:each="thirdMenu:${secondMenu.childList}">
<th:block th:each="cat3Code:${session.commonCode.get('CAT3')}"> <th:block th:each="cat3Code:${session.commonCode.get('CAT3')}">
<th:block th:if="${cat3Code.itemCd eq thirdMenu.cat3Cd}"> <th:block th:if="${cat3Code.itemCd eq thirdMenu.cat3Cd}">
<a class="nav-link link-dark" th:text="${cat3Code.itemValue}" th:href="${thirdMenu.menuUrl}"></a> <a class="nav-link link-dark" th:text="${cat3Code.itemValue}" th:href="${thirdMenu.menuUrl}"></a>
</th:block>
</th:block> </th:block>
</li> </th:block>
</ul> </li>
</div> </ul>
</th:block> </div>
</th:block> </th:block>
</li> </th:block>
</ul> </li>
</div> </ul>
</th:block> </div>
</th:block> </th:block>
</li> </th:block>
</ul> </li>
</div> </ul>
</div>
</html> </html>

View File

@ -17,10 +17,8 @@
<div layout:fragment="content"> <div layout:fragment="content">
<main class="pt-3"> <main class="pt-3">
<h4>마이페이지</h4> <h4>마이페이지</h4>
<input type="hidden" name="_csrf_header" th:value="${_csrf.headerName}"/>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<div class="row mx-0"> <div class="row mx-0">
<div class="col-12 card text-center"> <div class="col-12 card">
<div class="card-body"> <div class="card-body">
<ul class="nav nav-tabs" id="userTab" role="tablist"> <ul class="nav nav-tabs" id="userTab" role="tablist">
<li class="nav-item" role="presentation"> <li class="nav-item" role="presentation">
@ -32,7 +30,158 @@
</ul> </ul>
<div class="tab-content border border-top-0 p-2"> <div class="tab-content border border-top-0 p-2">
<div class="tab-pane fade p-2 show active" id="infoTabPanel" role="tabpanel" aria-labelledby="infoTabPanel" tabindex="0"> <div class="tab-pane fade p-2 show active" id="infoTabPanel" role="tabpanel" aria-labelledby="infoTabPanel" tabindex="0">
<div class="row justify-content-start">
<div class="col-7">
<form id="userInfoUpdate" action="#" method="post">
<input type="hidden" name="_csrf_header" th:value="${_csrf.headerName}"/>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<div class="mb-3 mt-3 row">
<label for="dicCode" class="col-sm-2 col-form-label col-form-label-sm text-center ">공무원식별번호</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="dicCode" name="dicCode" autocomplete="off" th:value="${userInfo.dicCode}">
</div>
<div class="col-sm-6">
<div class="row justify-content-end">
<div class="col-auto">
<button type="button" class="btn btn-sm btn-info" id="syncBtn" th:disabled="${#strings.isEmpty(userInfo.dicCode)}">인사시스템 정보 연동</button>
<label for="syncBtn" style="font-size: 12px" th:if="${#strings.isEmpty(userInfo.dicCode)}">공무원식별번호가 필요합니다.</label>
</div>
<div class="col-auto">
<button type="button" class="btn btn-sm btn-primary" id="updateBtn">수정</button>
</div>
</div>
</div>
</div>
<div class="mb-3 row">
<label for="userId" class="col-sm-2 col-form-label col-form-label-sm text-center ">아이디</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="userId" name="userId" autocomplete="off" th:value="${userInfo.userId}" readonly>
<label for="userId" style="font-size: 12px">아이디는 수정할 수 없습니다.</label>
</div>
<label for="userNm" class="col-sm-2 col-form-label col-form-label-sm text-center">이름</label>
<div class="col-sm-4">
<input type="text" class=" form-control form-control-sm" id="userNm" name="userNm" autocomplete="off" th:value="${userInfo.userNm}">
</div>
</div>
<div class="mb-3 row">
<label for="modalPassword" class="col-sm-2 col-form-label col-form-label-sm text-center">비밀번호</label>
<div class="col-sm-4">
<input type="password" class="form-control form-control-sm" id="modalPassword" name="password" autocomplete="off">
<label for="userId" style="font-size: 12px">8~16자 사이의 알파벳, 숫자, 특수문자 조합</label>
</div>
<label for="passwordConfirm" class="col-sm-2 col-form-label col-form-label-sm text-center">비밀번호 확인</label>
<div class="col-sm-4">
<input type="password" class="form-control form-control-sm" id="passwordConfirm">
</div>
</div>
<div class="mb-3 row">
<label for="phoneNo" class="col-sm-2 col-form-label col-form-label-sm text-center">휴대전화</label>
<div class="col-sm-4">
<input type="tel" class="form-control form-control-sm" id="phoneNo" name="phoneNo" th:value="${userInfo.phoneNo}">
</div>
<label for="email" class="col-sm-2 col-form-label col-form-label-sm text-center">이메일</label>
<div class="col-sm-4">
<input type="email" class="form-control form-control-sm" id="email" name="email" th:value="${userInfo.email}">
</div>
</div>
<div class="mb-3 row">
<label for="sex" class="col-sm-2 col-form-label col-form-label-sm text-center">성별</label>
<div class="col-sm-4">
<select class="form-select form-select-sm" id="sex" name="sex">
<option value="M" th:selected="${userInfo.sex eq 'M'}"></option>
<option value="F" th:selected="${userInfo.sex eq 'F'}"></option>
</select>
</div>
</div>
<div class="mb-3 row">
<label for="birthDate" class="col-sm-2 col-form-label col-form-label-sm text-center">생년월일</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm dateSelector" id="birthDate" name="birthDate" th:value="${userInfo.birthDate}" readonly>
</div>
<label for="policeInDate" class="col-sm-2 col-form-label col-form-label-sm text-center">해양경찰배명일</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm dateSelector" id="policeInDate" name="policeInDate" th:value="${userInfo.policeInDate}" readonly>
</div>
</div>
<div class="mb-3 row">
<label for="ogCd" class="col-sm-2 col-form-label col-form-label-sm text-center">관서</label>
<div class="col-sm-4">
<select class="form-select form-select-sm" id="ogCd" name="ogCd">
<option value="">--선택--</option>
<th:block th:each="code:${ogList}">
<option th:value="${code.itemCd}" th:text="${code.itemValue}" th:selected="${code.itemCd eq userInfo.ogCd}"></option>
</th:block>
</select>
</div>
<label for="organInDate" class="col-sm-2 col-form-label col-form-label-sm text-center">현관서전입일</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm dateSelector" id="organInDate" name="organInDate" th:value="${userInfo.organInDate}" readonly>
</div>
</div>
<div class="mb-3 row">
<label for="ofcCd" class="col-sm-2 col-form-label col-form-label-sm text-center">부서</label>
<div class="col-sm-4">
<select class="form-select form-select-sm" id="ofcCd" name="ofcCd">
<option value="">--선택--</option>
<th:block th:each="code:${ofcList}">
<option th:value="${code.itemCd}" th:text="${code.itemValue}" th:selected="${code.itemCd eq userInfo.ofcCd}"></option>
</th:block>
</select>
</div>
<label for="ofcInDate" class="col-sm-2 col-form-label col-form-label-sm text-center">현부서임용일</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm dateSelector" id="ofcInDate" name="ofcInDate" th:value="${userInfo.ofcInDate}" readonly>
</div>
</div>
<div class="mb-3 row">
<label for="ogCd" class="col-sm-2 col-form-label col-form-label-sm text-center">계급</label>
<div class="col-sm-4">
<select class="form-select form-select-sm" id="titleCd" name="titleCd">
<option value="">--선택--</option>
<th:block th:each="code:${titleList}">
<option th:value="${code.itemCd}" th:text="${code.itemValue}" th:selected="${code.itemCd eq userInfo.titleCd}"></option>
</th:block>
</select>
</div>
<label for="titleInDate" class="col-sm-2 col-form-label col-form-label-sm text-center">현계급임용일</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm dateSelector" id="titleInDate" name="titleInDate" th:value="${userInfo.titleInDate}" readonly>
</div>
</div>
<div class="mb-3 row">
<label for="outturnCd" class="col-sm-2 col-form-label col-form-label-sm text-center">경과</label>
<div class="col-sm-4">
<select class="form-select form-select-sm" id="outturnCd" name="outturnCd">
<option value="">--선택--</option>
<th:block th:each="code:${outturnList}">
<option th:value="${code.itemCd}" th:text="${code.itemValue}" th:selected="${code.itemCd eq userInfo.outturnCd}"></option>
</th:block>
</select>
</div>
<label for="seriesCd" class="col-sm-2 col-form-label col-form-label-sm text-center">직별</label>
<div class="col-sm-4">
<select class="form-select form-select-sm" id="seriesCd" name="seriesCd">
<option value="">--선택--</option>
<th:block th:each="code:${seriesList}">
<option th:value="${code.itemCd}" th:text="${code.itemValue}" th:selected="${code.itemCd eq userInfo.seriesCd}"></option>
</th:block>
</select>
</div>
</div>
<div class="mb-3 row">
<label for="languageCd" class="col-sm-2 col-form-label col-form-label-sm text-center">외국어특채</label>
<div class="col-sm-4">
<select class="form-select form-select-sm" id="languageCd" name="languageCd">
<option value="">--선택--</option>
<th:block th:each="code:${languageList}">
<option th:value="${code.itemCd}" th:text="${code.itemValue}" th:selected="${code.itemCd eq userInfo.languageCd}"></option>
</th:block>
</select>
</div>
</div>
</form>
</div>
</div>
</div> </div>
<div class="tab-pane fade p-2" id="dashboardTabPanel" role="tabpanel" aria-labelledby="dashboardTab" tabindex="0"> <div class="tab-pane fade p-2" id="dashboardTabPanel" role="tabpanel" aria-labelledby="dashboardTab" tabindex="0">
<div class="row justify-content-end"> <div class="row justify-content-end">
@ -94,42 +243,6 @@
</div> </div>
</div> </div>
</main> </main>
<div class="modal fade" id="passwordModifyModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="passwordModifyModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="passwordModifyModalLabel">비밀번호 변경</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body mx-4">
<form action="#" method="post" id="modifyPasswordForm">
<div class="mb-3 row">
<label for="password" class="col-sm-4 col-form-label text-end">현재 비밀번호</label>
<div class="col-sm-7">
<input type="password" class="form-control" id="password" name="password">
</div>
</div>
<div class="mb-3 row">
<label for="modifyPassword" class="col-sm-4 col-form-label text-end">새 비밀번호</label>
<div class="col-sm-7">
<input type="password" class="form-control" id="modifyPassword" name="modifyPassword">
</div>
</div>
<div class="mb-3 row">
<label for="passwordConfirm" class="col-sm-4 col-form-label text-end">새 비밀번호 확인</label>
<div class="col-sm-7">
<input type="password" class="form-control" id="passwordConfirm">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
<button type="button" class="btn btn-primary" id="savePasswordBtn">저장</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="menuModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="menuModalLabel" aria-hidden="true"> <div class="modal fade" id="menuModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="menuModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable"> <div class="modal-dialog modal-xl modal-dialog-scrollable">