My Project/amigo

[2일차] Admin Page - 회원 관리

미로910 2024. 11. 6. 17:45
CRUD
(1) xml
(2) model, DTO
(3) Interfaces -> Repository
(4) Service
(5) Controller
(6) 화면 구성

관리자 페이지에서 어떤 목적과 어떤 기능을 만들건지 잘 설계하고 들어가기!!

회원 관리 기능

  • -  회원 조회
  • -  회원 생성
  • -  회원 삭제
  • -  회원 수정

에서 조회랑 탈퇴(삭제) 기능만 만들 예정 

(생성과 수정은 다른 페이지에서 하기로 설계를 했습니다.)

 

sql
-- 유저 테이블
create table user_tb (
  id int primary key auto_increment,
  user_id varchar(50) not null,
  name varchar(20)  null,
  password varchar(1000) not null,
  nickname varchar(20) null,
  UNIQUE (nickname),
  phone_number varchar(20)  null,
  gender varchar(10)  null,
  profile Blob,
  birth int  null,
  point int default 0,
  user_role int default 0,
  online_status boolean default false,
  active_status varchar(7) default '활동중',
  created_at timestamp default CURRENT_TIMESTAMP
);


-- 탈퇴 사유 조회 테이블
create table withdrawal_reason_tb (
  id int primary key auto_increment,
  user_id int not null,
  reason varchar(255) not null,
  details text null,
  created_at timestamp default CURRENT_TIMESTAMP,
  foreign key (user_id) references user_tb(id) on delete cascade
);

 

xml
<?xml version="1.0" encoding="UTF-8" ?>
<!-- mapper DTD 선언 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.amigo_project.repository.interfaces.AdminRepository">


    <!-- 일반 유저 리스트 받아 오기 -->
    <select id="findUserAll" resultType="com.example.amigo_project.repository.model.User">
        SELECT *
        FROM user_tb
        WHERE user_role = 0
        AND active_status = '활동중'
    </select>

    <!-- 탈퇴 회원 조회 -->
    <select id="findDeletedUsers" resultType="com.example.amigo_project.repository.model.User">
        SELECT *
        FROM user_tb
        WHERE active_status = '탈퇴'
    </select>

    <!-- 탈퇴 사유 조회 -->
    <select id="findWithdrawalReason" parameterType="int" resultType="com.example.amigo_project.dto.WithdrawalReasonDTO">
        SELECT
        u.id,
        u.name AS user_name,
        wr.reason,
        wr.details,
        wr.created_at
        FROM
        withdrawal_reason_tb wr
        JOIN
        user_tb u ON wr.user_id = u.id
        WHERE
        wr.user_id = #{id}
    </select>

    <select id="findById" resultType="com.example.amigo_project.repository.model.User">
        SELECT * FROM user_tb WHERE id = #{id}
    </select>

    <!-- 유저 탈퇴 -->
    <update id="deactivatedUserId" parameterType="com.example.amigo_project.repository.model.User">
        UPDATE user_tb
        SET active_status = '탈퇴'
        WHERE id = #{id}
    </update>

    <!-- 탈퇴 해지 -->
    <update id="restoreUserStatus" parameterType="int">
        UPDATE user_tb
        SET active_status = '활동중'
        WHERE id = #{id}
    </update>

role로 유저와 관리자를 확인합니다 ➡️ where user_role= 0 로 유저만 조회

active_status로 현재 유저 상태를 확인합니다(활동, 탈퇴, 정지 등)

➡️ active_status로 탈퇴를 시킬 수 있습니다 / '활동중' 으로 update를 하면 탈퇴 해지를 시킬 수 있습니다

 

User (model)
/**
 * onlineStatus 접속상태 default 0
 * activeStatus 가입상태(탈퇴) default 0
 */
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
@Data
public class User {

    private Integer id; // (pk) auto_increment
    private String userId;
    private String name;
    private String password;
    private String nickname;
    private String phoneNumber;
    private String gender;
    private Integer birth;
    private Integer point;
    private Integer userRole;
    private byte[] profile;
    private boolean onlineStatus;
    private String activeStatus;
    private String school; 
    private Timestamp createdAt;
    private String createdAtFormat;
    private LocalDate suspensionEndDate;  // 정지 종료 날짜

    public void getFormattedCreatedAt() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        this.createdAtFormat = formatter.format(createdAt);
    }

}

 

WithdrawalReasonDTO (DTO)  // 탈퇴 사유 
@Data
public class WithdrawalReasonDTO {

    private Integer id;
    private String userName;
    private String reason;
    private String details;
    private Timestamp createdAt;

}

 

💡팁

resultType에 model을 넣어야 할지.. DTO를 넣어야 할지 잘 모르겠으면

 

  • Model: 데이터베이스의 엔티티와 매핑된 객체로, 조회 시 모든 필드를 포함하여 사용됩니다. 즉, 전체 정보를 필요로 할 때 사용합니다. 예를 들어, 특정 엔티티의 모든 속성 값을 가져와야 하는 경우 모델 객체를 사용합니다.
  • DTO (Data Transfer Object): 클라이언트나 다른 계층으로 데이터를 전달할 때, 필요한 필드만 선택적으로 포함하는 객체입니다. 부분적으로 필요한 정보만 추출하거나, 전송 데이터의 양을 줄이고 싶을 때 사용합니다.

 

model은 조회 -> 모든 정보를 조회할 때

dto는 부분적으로 사용할 때  사용하면 된다

 

Repository

@Mapper
public interface AdminRepository {


    // 유저 조회
    public List<User> findUserAll();

    // 탈퇴 회원 조회
    public List<User> findDeletedUsers();

    // 탈퇴 사유 조회
    public WithdrawalReasonDTO findWithdrawalReason(int id);

    // 탈퇴 해지
    public int restoreUserStatus(UserDTO userDTO);

    // 유저 상세보기 (Detail)
    public User findById(int id);

    // 유저 탈퇴 처리
    public int deactivatedUserId(int id);

 
}

 

Service
@Service
@RequiredArgsConstructor
public class AdminService {



    private final AdminRepository adminRepository;
    private final NoticeRepository noticeRepository;

    // 유저 조회
    public List<User> getUserList(){
        
        List<User> userList = adminRepository.findUserAll();
        return userList;
    }

// 상세보기 (특정 유저 조회)
    public User findById(int id){
        User user = adminRepository.findById(id);

        return user;
    }

    // 유저 탈퇴
    public void deactivatedUserId(int id){
        adminRepository.deactivatedUserId(id);
    }

    // 탈퇴 회원 조회
    public List<User> findDeletedUsers(){
        return adminRepository.findDeletedUsers();
    }

    // 탈퇴 사유 조회
    public WithdrawalReasonDTO findWithdrawalReason(int id) {
       WithdrawalReasonDTO reason = adminRepository.findWithdrawalReason(id);
        return reason;
    }

    // 탈퇴 해지
    public int restoreUserStatus(UserDTO userDTO) {
        return adminRepository.restoreUserStatus(userDTO);
    }


   
}

 

Controller

@Controller
@RequiredArgsConstructor
@RequestMapping("/admin")
public class AdminController {

    private final AdminService adminService;
  
    // 메인 화면
    @GetMapping("/main")
    public String home() {
        return "views/admins/admin"; // index.mustache 파일을 반환 (임시)
    }

    /**
     * 회원관리
     * @param model
     * @return
     */
    // 회원 관리 - 유저 관리 페이지
    @GetMapping("/user")
    public String userPage(Model model){
        List<User> userList = adminService.getUserList();

        model.addAttribute("userList", userList);
        return "views/admins/user"; // 임시
    }



    //    // 유저 탈퇴
    @PostMapping("/deleteUsers/{id}")
    public String deleteUser(@PathVariable(name = "id") Integer id){
        adminService.deactivatedUserId(id);
        return "redirect:/admin/user/detail/" + id;
    }


    // 탈퇴 회원 조회
    @GetMapping("/deletedUsers")
    public String deletedUsersPage(Model model){
        List<User> deletedUser = adminService.findDeletedUsers();
        model.addAttribute("deletedUser", deletedUser);
        return "views/admins/deletedUsers";
    }

    // 특정 유저의 탈퇴 사유 조회
    @GetMapping("/deletedUsers/withdrawalReason/{id}")
    @ResponseBody
    public WithdrawalReasonDTO findWithdrawalReason(@PathVariable("id") int id) {
        WithdrawalReasonDTO reason = adminService.findWithdrawalReason(id);
        System.out.println("조회된 탈퇴 사유: " + reason); // 탈퇴 사유 데이터 출력
        return reason;
    }

    // 탈퇴 해지 요청
    @PostMapping("/restoreUser")
    public ResponseEntity<String> restoreUserStatus(@RequestBody UserDTO userDTO) {
        int result = adminService.restoreUserStatus(userDTO);
        if (result > 0) {
            return ResponseEntity.ok("탈퇴 해지 되었습니다.");
        } else {
            return ResponseEntity.status(400).body("탈퇴 해지에 실패했습니다.");
        }
    }



    // 유저 관리 - 상세보기
    @GetMapping("/user/detail/{id}")
    public String userDetail(Model model, @PathVariable(name = "id") int id){
        User user = adminService.findById(id);
        System.out.println(user);
        // 게시글 개수 조회
        AdminDTO adminDTO = adminService.findBoardCount(id);
        // 댓글 개수 조회
        CommentDTO commentDTO = adminService.findCommentCount(id);
        // 시간
        user.getFormattedCreatedAt();
        model.addAttribute("user", user);
        System.out.println("게시글 수 : " + adminDTO.getBoardCount());
        System.out.println("댓글 수 : " + commentDTO.getCommentCount());
        model.addAttribute("boardCount",adminDTO.getBoardCount());
        model.addAttribute("commentCount",commentDTO.getCommentCount());
        return "views/admins/userDetail"; // 임시

    }

}

 

화면 구성 (mustache 사용)

[회원조회 - 목록]


<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>회원 조회</title>
    <!-- DataTables CSS -->
    <link rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css">
    <!-- Custom CSS -->
    <style>
        /* 기본 스타일 */
        body {
            font-family: 'Arial', sans-serif;
            background-color: #f8f9fc;
        }
        h1.h3, h6.m-0 {
            color: #4e73df;
        }
        /* 테이블 스타일 */
        .table thead th {
            background-color: #4e73df;
            color: white;
            text-align: center;
        }
        .table td {
            vertical-align: middle;
            text-align: center;
        }
        /* 상태 아이콘 */
        .status-icon {
            width: 24px;
            height: 24px;
        }
        /* DataTable 검색 및 페이지네이션 커스터마이징 */
        .dataTables_filter {
            float: right;
            text-align: right;
        }
        .dataTables_length {
            float: left;
        }
        .dataTables_info {
            float: left;
            margin-top: 10px;
        }
        .dataTables_paginate {
            float: right;
            margin-top: 10px;
        }
    </style>
</head>
<body id="page-top">

{{>layout/admin/adminSidebar}}
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
    <div id="content">
        <!-- Main Content -->
        <div class="container-fluid">
            <h1 class="h3 mb-2 text-gray-800">회원 조회</h1><br>
            <div class="card shadow mb-4">
                <div class="card-header py-3">
                    <h6 class="m-0 font-weight-bold text-secondary">회원 목록</h6>
                </div>
                <div class="card-body">
                    <div class="table-responsive">
                        <table class="table table-bordered" id="userTable" width="100%" cellspacing="0">
                            <thead>
                            <tr>
                                <th>이름</th>
                                <th>아이디</th>
                                <th>온라인 상태</th>
                                <th>활성상태</th>
                                <th>상세보기</th>
                            </tr>
                            </thead>
                            <tbody>
                            {{#userList}}
                                <tr>
                                    <td>{{name}}</td>
                                    <td>{{userId}}</td>
                                    <td>
                                        {{#onlineStatus}}
                                            <img src="/image/admin/free-icon-checkmark.png" class="status-icon" alt="온라인 상태">
                                        {{/onlineStatus}}
                                        {{^onlineStatus}}
                                            <img src="/image/admin/free-icon-delete.png" class="status-icon" alt="오프라인 상태">
                                        {{/onlineStatus}}
                                    </td>
                                    <td>{{activeStatus}}</td>
                                    <td><a href="/admin/user/detail/{{id}}" class="btn btn-primary btn-sm">상세보기</a></td>
                                </tr>
                            {{/userList}}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
        <!-- End of Main Content -->
    </div>
</div>
<!-- End of Content Wrapper -->

<!-- JavaScript Files Load -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
<script src="/vendor/js/sb-admin-2.min.js"></script>

<script>
    $(document).ready(function() {
        var table = $('#userTable').DataTable({
            "paging": true, // 페이지네이션 활성화
            "pageLength": 10, // 한 페이지에 표시할 행 수
            "language": {
                "search": "검색:",
                "lengthMenu": "페이지당 _MENU_ 개 보기",
                "info": "총 _TOTAL_명의 회원 중 _START_에서 _END_까지 표시",
                "paginate": {
                    "previous": "이전",
                    "next": "다음"
                }
            }
        });

        // 전체 검색 필드를 이름, 아이디 열로 제한하는 커스텀 검색 기능 추가
        $.fn.dataTable.ext.search.push(
            function(settings, data, dataIndex) {
                var searchTerm = $('#userTable_filter input').val().toLowerCase();
                var name = data[0].toLowerCase();  // 이름 열
                var userId = data[1].toLowerCase();  // 아이디 열

                // 이름이나 아이디 열에 검색어가 포함되어 있는 경우에만 결과로 포함
                if (name.includes(searchTerm) || userId.includes(searchTerm)) {
                    return true;
                }
                return false;
            }
        );

        // 검색 필드에 입력될 때마다 테이블 다시 그리기
        $('#userTable_filter input').on('keyup change', function() {
            table.draw();
        });
    });
</script>

</body>
</html>

[회원조회 - 상세보기]

{{>layout/admin/adminSidebar}}

<div id="content-wrapper" class="d-flex flex-column">
    <div id="content">
        <div class="container-fluid">
            <h1 class="h3 mb-2 text-gray-800">회원 상세보기</h1>
            <br><br>
            <div class="row align-items-stretch">
                <div class="col-lg-6 d-flex mb-4">
                    <div class="card w-100 border-0">
                        <div class="card-header py-3 bg-light">
                            <h6 class="m-0 font-weight-bold text-secondary">회원 정보</h6>
                        </div>
                        <div class="card-body">
                            <h5 class="font-weight-bold">{{user.nickname}} : 회원 정보</h5><br>
                            <table class="table table-sm table-borderless">
                                <tbody>
                                <tr>
                                    <th>아이디 :</th>
                                    <td>{{user.userId}}</td>
                                </tr>
                                <tr>
                                    <th>비밀번호 :</th>
                                    <td>********</td>
                                </tr>
                                <tr>
                                    <th>이름 :</th>
                                    <td>{{user.nickname}}</td>
                                </tr>
                                <tr>
                                    <th>휴대폰 번호 :</th>
                                    <td>{{user.phoneNumber}}</td>
                                </tr>
                                <tr>
                                    <th>성별 :</th>
                                    <td>{{user.gender}}</td>
                                </tr>
                                <tr>
                                    <th>나이 :</th>
                                    <td>{{user.birth}}살</td>
                                </tr>
                                </tbody>
                            </table>
                            <button class="btn btn-danger btn-sm mt-3" onclick="deletePost({{user.id}})">탈퇴 처리</button>
                        </div>
                    </div>
                </div>

                <div class="col-lg-6 d-flex mb-4">
                    <div class="card w-100 border-0">
                        <div class="card-header py-3 bg-light">
                            <h6 class="m-0 font-weight-bold text-secondary">활동 정보</h6>
                        </div>
                        <div class="card-body">
                            <table class="table table-sm table-borderless">
                                <tbody>
                                <tr>
                                    <th>가입일 :</th>
                                    <td data-created-at>{{user.createdAtFormat}}</td>
                                </tr>
                                <tr>
                                    <th>게시글 수 :</th>
                                    <td>{{boardCount}}개</td>
                                </tr>
                                <tr>
                                    <th>댓글 수 :</th>
                                    <td>{{commentCount}}개</td>
                                </tr>
                                <tr>
                                    <th>포인트 :</th>
                                    <td>{{user.point}}</td>
                                </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
                <div class="d-flex justify-content-end w-100 mt-3">
                    <a href="/admin/user" class="btn btn-secondary btn-sm">뒤로가기</a>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- JavaScript -->
<script src="/vendor/jquery/jquery.min.js"></script>
<script src="/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="/vendor/jquery-easing/jquery.easing.min.js"></script>
<script src="/vendor/js/sb-admin-2.min.js"></script>

<script>
    $(document).ready(function () {
        const createdAtElement = document.querySelector('td[data-created-at]');
        if (createdAtElement) {
            createdAtElement.textContent = formatDate(createdAtElement.textContent);
        }
    });

    function formatDate(dateString) {
        const date = new Date(dateString);
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        return `${year}-${month}-${day}`;
    }

    function deletePost(postId) {
        if (confirm('정말로 탈퇴하시겠습니까?')) {
            $.ajax({
                url: '/admin/deleteUsers/' + postId,
                type: 'POST',
                success: function () {
                    alert('탈퇴 완료되었습니다.');
                    window.location.href = "/admin/user";
                },
                error: function () {
                    alert('삭제에 실패했습니다. 다시 시도해주세요.');
                }
            });
        }
    }
</script>

</body>
</html>

[탈퇴 회원 조회 - 목록 ]

<link rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css">

<style>
    .status-icon {
        width: 24px;
        height: 24px;
    }
    .modal {
        display: none;
        position: fixed;
        z-index: 1;
        padding-top: 100px;
        left: 0;
        top: 0;
        height: 100%;
        overflow: auto;
        background-color: rgba(0, 0, 0, 0.4);
    }
    .modal-content {
        background-color: #fefefe;
        margin: auto;
        padding: 20px;
        border: 1px solid #888;
        width: 45% !important;
    }
    .close {
        color: #aaa;
        float: right;
        font-size: 28px;
        font-weight: bold;
    }
    .close:hover,
    .close:focus {
        color: black;
        text-decoration: none;
        cursor: pointer;
    }
</style>

<body id="page-top">

{{>layout/admin/adminSidebar}}
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
    <div id="content">
        <!-- Main Content -->
        <div class="container-fluid">
            <h1 class="h3 mb-2 text-gray-800">탈퇴 회원 조회</h1><br>
            <div class="card shadow mb-4">
                <div class="card-header py-3">
                    <h6 class="m-0 font-weight-bold text-secondary">탈퇴 회원 목록</h6>
                </div>
                <div class="card-body">
                    <div class="table-responsive">
                        <table class="table table-bordered" id="userTable" width="100%" cellspacing="0">
                            <thead>
                            <tr>
                                <th>이름</th>
                                <th>아이디</th>
                                <th>활성상태</th>
                                <th>상세보기</th>
                                <th>탈퇴 해지</th> <!-- 탈퇴 해지 버튼 열 -->
                            </tr>
                            </thead>
                            <tbody>
                            {{#deletedUser}}
                                <tr>
                                    <td>{{name}}</td>
                                    <td>{{userId}}</td>
                                    <td>{{activeStatus}}</td>
                                    <td><button class="btn btn-primary btn-sm detail-btn" data-id="{{id}}">상세보기</button></td>
                                    <td><button class="btn btn-success btn-sm restore-btn" data-id="{{id}}">탈퇴 해지</button></td> <!-- 탈퇴 해지 버튼 -->
                                </tr>
                            {{/deletedUser}}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
        <!-- End of Main Content -->
    </div>
</div>
<!-- End of Content Wrapper -->

<!-- Modal -->
<div id="detailModal" class="modal">
    <div class="modal-content">
        <span class="close">&times;</span>
        <h2>탈퇴 사유</h2>
        <p><strong>사유:</strong> <span id="withdrawReason">탈퇴 사유를 불러오는 중...</span></p>
        <p><strong>상세 내용:</strong> <span id="withdrawDetails">상세 내용을 불러오는 중...</span></p>
        <p><strong>탈퇴 날짜:</strong> <span id="withdrawDate">날짜를 불러오는 중...</span></p>
    </div>
</div>

<!-- JavaScript Files Load -->
<!-- jQuery CDN -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<!-- Bootstrap JS CDN -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>

<!-- DataTables JavaScript -->
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>

<!-- Custom scripts for all pages-->
<script src="/vendor/js/sb-admin-2.min.js"></script>

<script>
    $(document).ready(function() {
      var table = $('#userTable').DataTable({
          "language": {
              "search": "검색:",
              "lengthMenu": "_MENU_ 개씩 보기",
              "info": "총 _TOTAL_명의 회원 중 _START_에서 _END_까지 표시",
              "paginate": {
                  "previous": "이전",
                  "next": "다음"
              }
          }
      });

      // 전체 검색 필드를 특정 열로만 제한하는 커스텀 검색 기능 추가
      $.fn.dataTable.ext.search.push(
          function(settings, data, dataIndex) {
              var searchTerm = $('#userTable_filter input').val().toLowerCase();
              var name = data[0].toLowerCase();  // 이름 열
              var userId = data[1].toLowerCase();  // 아이디 열

              if (name.includes(searchTerm) || userId.includes(searchTerm)) {
                  return true;
              }
              return false;
          }
      );

      // 검색 필드에 입력될 때마다 테이블 다시 그리기
      $('#userTable_filter input').on('keyup change', function() {
          table.draw();
      });

      // Modal 관련 스크립트
      var modal = $('#detailModal');
      var span = $('.close');

      // 상세보기 버튼 클릭 시
      $('.detail-btn').on('click', function() {
          var userId = $(this).data('id');

          // AJAX를 사용해 특정 유저의 탈퇴 사유를 가져옵니다
          $.ajax({
              url: '/admin/deletedUsers/withdrawalReason/' + userId,
              method: 'GET',
              success: function(response) {
                  console.log(response); // 응답을 확인해 보기 위해 콘솔에 출력

                  if (response) {
                      // 탈퇴 사유와 관련된 데이터를 안전하게 설정
                      $('#withdrawReason').text(response.reason ? response.reason : '사유가 없습니다.');
                      $('#withdrawDetails').text(response.details ? response.details : '상세 내용이 없습니다.');

                      // createdAt 필드가 존재하고 유효한지 확인 후 처리
                      if (response.createdAt) {
                          try {
                              const withdrawalDate = response.createdAt.replace(" ", "T");
                              $('#withdrawDate').text(new Date(withdrawalDate).toLocaleDateString());
                          } catch (e) {
                              console.error('날짜 형식 오류:', e);
                              $('#withdrawDate').text('날짜 형식이 잘못되었습니다.');
                          }
                      } else {
                          $('#withdrawDate').text('탈퇴 날짜를 불러오지 못했습니다.');
                      }
                  } else {
                      $('#withdrawReason').text('탈퇴 사유를 불러오지 못했습니다.');
                      $('#withdrawDetails').text('상세 내용을 불러오지 못했습니다.');
                      $('#withdrawDate').text('날짜를 불러오지 못했습니다.');
                  }

                  modal.show();
              },
              error: function(xhr, status, error) {
                  console.error("AJAX 요청 실패:", error);

                  // 오류 발생 시 모달 내용 초기화 후 알림
                  $('#withdrawReason').text('탈퇴 사유를 불러오지 못했습니다.');
                  $('#withdrawDetails').text('상세 내용을 불러오지 못했습니다.');
                  $('#withdrawDate').text('날짜를 불러오지 못했습니다.');

                  modal.show();
              }
          });
      });


          // 탈퇴 해지 버튼 클릭 시
          $('.restore-btn').on('click', function() {
              var userId = $(this).data('id');
              $.ajax({
                  url: '/admin/restoreUser',
                  method: 'POST',
                  contentType: 'application/json',
                  data: JSON.stringify({ id: userId }),
                  success: function(response) {
                      alert(response); // 성공 메시지 표시
                      location.reload(); // 페이지 새로고침으로 변경된 상태 반영
                  },
                  error: function() {
                      alert('탈퇴 해지에 실패했습니다.');
                  }
              });
          });

          // 모달 닫기 버튼 클릭 시
          span.on('click', function() {
              modal.hide();
          });

          // 모달 바깥 클릭 시 모달 닫기
          $(window).on('click', function(event) {
              if (event.target == modal[0]) {
                  modal.hide();
              }
          });
      });
</script>

</body>
</html>

➡️ 탈퇴 상세보기는 (modal) 모달 창을 이용해서 조회하기

 

 

'My Project > amigo' 카테고리의 다른 글

[3일차] Admin Page - 게시글 관리  (0) 2024.11.25
[1일차] Admin Page Bootstrap 사용  (2) 2024.10.18