[3차 팀프로젝트] 🌎🪐⭐️3차 팀 프로젝트 WORLD 기술서

Glen(OH TaekJoo)·2023년 8월 16일
0

Study

목록 보기
36/53

🌎🪐⭐️3차 팀 프로젝트 WORLD 기술서

'WORLD' 는 게임 시리얼넘버(접속코드) 판매 쇼핑몰 사이트입니다.

게임 구매 , 리뷰 , 문의 , 최신게임 출시정보확인 등 컨텐츠 이용이 가능합니다

프로젝트 산출물

발표영상
movie
진행 기간: 2023.08.01 ~ 2023.08.30



😃 팀원




목차


🔗 배포 링크

https://www.world.gh5.site


🌎배포 환경

🔗 프로젝트 저장소

팀 이름GitHub Repository
World-GitHub Url

🤝 팀 규칙

브랜치 전략

  • upstream에는 main 브랜치만 존재
  • 브랜치명: 작업명/작업자이니셜
    • ex: adminorder/otj
  • 코드리뷰 받고 승인 받으면 origin:main에 merge

### 협업 툴 Trello

📂 폴더 구조

📦world
  ├── 📄스타일.css
  ├── 📄template.html
  ├── 📄test.java
  ├── 📄test.java
  ├── 📂admin
  ├── 📂calenbar
  ├── 📂email
  ├── 📂file
  ├── 📂mypage
  └── 📂notice
  └── 📂order
  └── 📂product
  └── 📂qna
  └── 📂qnaAnswer
  └── 📂review
  └── 📂user

🛠️ 기술 스택

개발도구

- SpringBoot
- JAVA
- Thymeleaf
- MariaDB
- HTML
- CSS
- JS
- Ajax
- Bootstrap
- Tailwind css
- CentOS
- jQuery
- NAVER Cloud

개발환경

- IntelliJ IDEA
- DBeaver
- Termius
- GitHub-Action CI/CD

📖 서비스 소개

기능 구현

  • 회원 가입
  • 상품상세
  • 상품구매
  • 상품목록
  • 관리자페이지
  • 마이페이지

ERD

페이지

회원가입
회원가입
상품상세
상품상세
상품구매
상품구매
상품목록
상품목록
관리자페이지
관리자페이지
마이페이지*
마이페이지

👑 구현미리보기

구현사항


📌 회원가입

  1. 이메일
  • 내용
    1) 설명

    @GetMapping("/mailCheck")
    @ResponseBody
    public int processMailCheck(@RequestParam("email") String email) throws Exception {
        int mailKey = (int) ((Math.random() * (99999 - 10000 + 1)) + 10000);
    
        String to = email;
        String title = "환영합니다! WORLD 입니다. 회원가입시 필요한 인증번호 입니다.";
        String content = "[인증번호] " + mailKey + " 입니다. <br/> 인증번호 확인란에 기입해주세요.";
        try {
            MimeMessage mail = mailSender.createMimeMessage();
            MimeMessageHelper mailHelper = new MimeMessageHelper(mail, true, "UTF-8");
    
            mailHelper.setTo(to);
            mailHelper.setSubject(title);
            mailHelper.setText(content, true);
    
            mailSender.send(mail);
    
        } catch (Exception e) {
            throw new DataNotFoundException("error");
        }
        return mailKey;
    }
  1. 닉네임 중복 확인
  • 내용
    1) 설명

    ```js
    	$.ajax({
      url: '/user/checkDuplicate',
      type: 'GET',
      dataType: 'JSON',
      data: {
        nickname: nickname
      },
      success: function(response) {
        if (!response) {
          isNicknameDuplicate = false;
        }
    
        if (isNicknameDuplicate) {
          $('#nicknameCheckResult')
            .text('이미 사용 중인 닉네임입니다.')
            .css('color', 'red')
            .css('margin-left', '40px');
        } else {
          $('#nicknameCheckResult')
            .text('사용 가능한 닉네임입니다.')
            .css('margin-left', '70px')
            .css('color', 'white');
        }
      },
      error: function(xhr, status, error) {
        console.error('유저 삭제 오류:', error);
      }
    });

    }

    ```

📌 관리자페이지 매출

  • 컨트롤러
	@PostMapping("/")
    public String adminMainSearsh(Model model, @Valid AdminSearchForm adminSearchForm, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "redirect:/ad/order";
        }
        LocalDateTime start = adminSearchForm.getStart();
        LocalDateTime end = adminSearchForm.getEnd();
        List<ProductOrder> list = this.orderService.getOrdersBetweenDates(start,end);

        int num=list.size();
        int totalPrice=1;
        for (ProductOrder order : list) {
            Product product = order.getProduct();
            if (product != null) {
                totalPrice += product.getPrice();
            }
        }
        DecimalFormat decimalFormat = new DecimalFormat("#,###");
        String formattedAllPrice = decimalFormat.format(totalPrice);

        LocalDate todayLocalDate = LocalDate.now();

        int priceM1 = this.adminService.requestMonthPrice(YearMonth.now());
        int priceM2 = this.adminService.requestMonthPrice(this.adminService.MonthMinus(1));
        int priceM3 = this.adminService.requestMonthPrice(this.adminService.MonthMinus(2));
        int priceM4 = this.adminService.requestMonthPrice(this.adminService.MonthMinus(3));
        int priceM5 = this.adminService.requestMonthPrice(this.adminService.MonthMinus(4));
        String month1 = YearMonth.now().toString();
        String month2 = this.adminService.MonthMinus(1).toString();
        String month3 = this.adminService.MonthMinus(2).toString();
        String month4 = this.adminService.MonthMinus(3).toString();
        String month5 = this.adminService.MonthMinus(4).toString();

        model.addAttribute("month1",month1);
        model.addAttribute("month2",month2);
        model.addAttribute("month3",month3);
        model.addAttribute("month4",month4);
        model.addAttribute("month5",month5);
        model.addAttribute("priceM1",priceM1);
        model.addAttribute("priceM2",priceM2);
        model.addAttribute("priceM3",priceM3);
        model.addAttribute("priceM4",priceM4);
        model.addAttribute("priceM5",priceM5);
        model.addAttribute("listSize",num);
        model.addAttribute("allPrice",formattedAllPrice);
        return "admin/admin_main";
    }
  • 템플릿
<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/172203/font-awesome.min.css">
  <link rel="stylesheet" href="/layout/admin.css"/>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.1.0/chart.min.js"></script>
</head>

<body>
<nav class="navbar navbar-default no-margin">
  <!-- Brand and toggle get grouped for better mobile display -->
  <div class="navbar-header fixed-brand">
    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" id="menu-toggle">
      <span class="glyphicon glyphicon-th-large" aria-hidden="true"></span>
    </button>
    <a class="navbar-brand" th:href="@{/}"><img class="rogoimg" src="https://i.postimg.cc/qRMyWWkr/image.png"/></a>
  </div>
  <!-- navbar-header-->
  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
    <ul class="nav navbar-nav">

    </ul>
  </div>
  <!-- bs-example-navbar-collapse-1 -->
</nav>
<div id="wrapper">
  <!-- Sidebar -->
  <div id="sidebar-wrapper">
    <ul class="sidebar-nav nav-pills nav-stacked" id="menu">
      <li>
        <a th:href="@{/admin/}"><span class="fa-stack fa-lg pull-left"><i class="fa fa-cloud-download fa-stack-1x "></i></span>매출</a>
      </li>
      <li>
        <a th:href="@{/admin/order}"><span class="fa-stack fa-lg pull-left"><i class="fa fa-cart-plus fa-stack-1x "></i></span>주문 관리</a>
      </li>
      <li>
        <a th:href="@{/admin/product}"><span class="fa-stack fa-lg pull-left"><i class="fa fa-cart-plus fa-stack-1x "></i></span>상품 관리</a>
      </li>
      <li>
        <a th:href="@{/admin/user}"><span class="fa-stack fa-lg pull-left"><i class="fa fa-wrench fa-stack-1x "></i></span>회원 관리</a>
      </li>
      <li>
        <a th:href="@{/admin/review}"><span class="fa-stack fa-lg pull-left"><i class="fa fa-server fa-stack-1x "></i></span>리뷰 관리</a>
      </li>
      <li>
        <a th:href="@{/admin/qna}"><span class="fa-stack fa-lg pull-left"><i class="fa fa-server fa-stack-1x "></i></span>문의사항 관리</a>
      </li>
      <li>
        <a th:href="@{/admin/notice}"><span class="fa-stack fa-lg pull-left"><i class="fa fa-server fa-stack-1x "></i></span>공지사항 관리</a>
      </li>
    </ul>
  </div>
  <!-- /#sidebar-wrapper -->
  <!-- Page Content -->
  <div id="page-content-wrapper">
    <div class="container-fluid xyz">
      <div class="row">
        <div class="col-lg-12">
          <h1>매출</h1>

          <div class="date_content">
            <div class="date_title"><p>기간별 조회. </p></div>
            <form th:action="@{/ad}" th:object="${adminSearchForm}" method="POST" class="date_form">
              <div class="birthday">
                <p>조회기간 :</p>
                <input type="datetime-local" th:field="*{start}">
                <p>~</p>
                <input type="datetime-local" th:field="*{end}">
                <button type="submit" class="date_btn"> 조회하기 </button>
              </div>
            </form>
            <div class="date_data"><div>
              <p >기간 내 판매 건 수 :</p>
              <p th:text="${listSize}">10(타임리프)</p>
              <p></p>
            </div>
              <div>
                <p>기간 내 총 매출 :</p>
                <p th:text="${allPrice}"></p>
                <p>won</p>
              </div>
            </div>
          </div>

          <div class="date_content">
            <div class="date_title"><p>매출 동향 </p></div>
            <canvas id="myChart"></canvas>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- /#page-content-wrapper -->
</div>
<!-- /#wrapper -->
<!-- jQuery -->

<script>
    var ctx = document.getElementById('myChart').getContext('2d');
    var priceM1 = [[${priceM1}]];
    var priceM2 = [[${priceM2}]];
    var priceM3 = [[${priceM3}]];
    var priceM4 = [[${priceM4}]];
    var priceM5 = [[${priceM5}]];
    var month1 = '[[${month1}]]';
    var month2 = '[[${month2}]]';
    var month3 = '[[${month3}]]';
    var month4 = '[[${month4}]]';
    var month5 = '[[${month5}]]';

    console.log(month4.toString())
    var chart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: [month5, month4, month3, month2, month1],
            datasets: [{
                label: '매출 (단위 : 원)',
                backgroundColor: 'rgb(255, 99, 132)',
                borderColor: 'rgb(255, 99, 132)',
                data: [priceM5, priceM4, priceM3, priceM2, priceM1]
            }]
        },
    });
</script>
</body>



</html>

👨‍👨‍👧‍👦 단위업무표




감사합니다🙆🏼‍♀️

profile
병아리 개발자 의 우당탕탕 성장기

1개의 댓글

comment-user-thumbnail
2023년 8월 16일

정보 감사합니다.

답글 달기