فهرست منبع

관리자 페이지

inkoreakim 2 سال پیش
والد
کامیت
bc5c1d79d7
26فایلهای تغییر یافته به همراه743 افزوده شده و 14 حذف شده
  1. 1 0
      build.gradle
  2. 55 0
      src/main/generated/com/example/ili_web/member/domain/QMember.java
  3. 1 1
      src/main/java/com/example/ili_web/board/repository/BoardRepositoryDsl.java
  4. 14 0
      src/main/java/com/example/ili_web/config/PasswordEncoderConfig.java
  5. 28 2
      src/main/java/com/example/ili_web/main/controller/MainController.java
  6. 23 0
      src/main/java/com/example/ili_web/member/controller/MemberController.java
  7. 35 0
      src/main/java/com/example/ili_web/member/domain/Member.java
  8. 9 0
      src/main/java/com/example/ili_web/member/dto/LoginReq.java
  9. 8 0
      src/main/java/com/example/ili_web/member/repository/MemberRepository.java
  10. 32 0
      src/main/java/com/example/ili_web/member/service/MemberService.java
  11. 118 0
      src/main/resources/static/css/backoffice.css
  12. 53 0
      src/main/resources/static/css/login.css
  13. 21 0
      src/main/resources/static/js/admin/adminChangeInner.js
  14. 11 0
      src/main/resources/static/js/admin/adminGetData.js
  15. 36 0
      src/main/resources/static/js/admin/adminMakeHtml.js
  16. 0 0
      src/main/resources/static/js/admin/adminNotice.js
  17. 17 0
      src/main/resources/static/js/admin/login.js
  18. 8 0
      src/main/resources/static/js/common/dateFormatter.js
  19. 0 0
      src/main/resources/static/js/contact/authPhone.js
  20. 0 4
      src/main/resources/static/js/contact/getList.js
  21. 3 4
      src/main/resources/static/js/contact/makeHtml.js
  22. 11 0
      src/main/resources/templates/html/admin/admin-notice-detail.html
  23. 130 0
      src/main/resources/templates/html/admin/admin-notice.html
  24. 82 0
      src/main/resources/templates/html/admin/backoffice.html
  25. 45 0
      src/main/resources/templates/html/admin/login.html
  26. 2 3
      src/main/resources/templates/html/contact-us.html

+ 1 - 0
build.gradle

@@ -25,6 +25,7 @@ repositories {
 
 dependencies {
     implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
+    implementation 'org.springframework.security:spring-security-crypto:5.7.1'
     implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
     implementation 'org.springframework.boot:spring-boot-starter-graphql'
     implementation 'org.springframework.boot:spring-boot-starter-web'

+ 55 - 0
src/main/generated/com/example/ili_web/member/domain/QMember.java

@@ -0,0 +1,55 @@
+package com.example.ili_web.member.domain;
+
+import static com.querydsl.core.types.PathMetadataFactory.*;
+
+import com.querydsl.core.types.dsl.*;
+
+import com.querydsl.core.types.PathMetadata;
+import javax.annotation.processing.Generated;
+import com.querydsl.core.types.Path;
+
+
+/**
+ * QMember is a Querydsl query type for Member
+ */
+@Generated("com.querydsl.codegen.DefaultEntitySerializer")
+public class QMember extends EntityPathBase<Member> {
+
+    private static final long serialVersionUID = -1935065612L;
+
+    public static final QMember member = new QMember("member1");
+
+    public final StringPath address = createString("address");
+
+    public final StringPath email = createString("email");
+
+    public final NumberPath<Long> id = createNumber("id", Long.class);
+
+    public final StringPath name = createString("name");
+
+    public final StringPath password = createString("password");
+
+    public final StringPath regDt = createString("regDt");
+
+    public final StringPath type = createString("type");
+
+    public final StringPath upDt = createString("upDt");
+
+    public final StringPath userId = createString("userId");
+
+    public final StringPath useYn = createString("useYn");
+
+    public QMember(String variable) {
+        super(Member.class, forVariable(variable));
+    }
+
+    public QMember(Path<? extends Member> path) {
+        super(path.getType(), path.getMetadata());
+    }
+
+    public QMember(PathMetadata metadata) {
+        super(Member.class, metadata);
+    }
+
+}
+

+ 1 - 1
src/main/java/com/example/ili_web/board/repository/BoardRepositoryDsl.java

@@ -15,6 +15,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Repository;
 
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 
 @RequiredArgsConstructor
@@ -25,7 +26,6 @@ public class BoardRepositoryDsl {
 
     public BoardRes boardList(BoardReq req) {
         BoardRes res = new BoardRes();
-
         List<BoardList> bList = queryFactory
                 .select(Projections.fields(BoardList.class, b.id, b.title, b.userName, b.content, b.type, b.regDt))
                 .from(b)

+ 14 - 0
src/main/java/com/example/ili_web/config/PasswordEncoderConfig.java

@@ -0,0 +1,14 @@
+package com.example.ili_web.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@Configuration
+public class PasswordEncoderConfig {
+    @Bean
+    public PasswordEncoder passwordEncoder () {
+        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
+    }
+}

+ 28 - 2
src/main/java/com/example/ili_web/main/controller/MainController.java

@@ -63,15 +63,41 @@ public class MainController {
         return HTML_PATH + "info-plaza.html";
     }
 
+    /**
+     method -> contactUs
+     description -> 고객센터 페이지이동
+     @author -> 김주한
+     @return -> html
+     date -> 2024.03.14
+     **/
     @GetMapping("/contact-us")
     public String contactUs () {
         log.info("========== Move to info-plaza ==========");
         return HTML_PATH + "contact-us.html";
     }
 
+    /**
+     method -> logiAdvice
+     description -> 물류자문 페이지
+     @author -> 김주한
+     @return -> html
+     date -> 2024.03.20
+     **/
     @GetMapping("/logi/advice")
-    public String test () {
-        log.info("========== Move to info-asd ==========");
+    public String logiAdvice () {
+        log.info("========== Move to logi-advice ==========");
         return HTML_PATH + "contact-inner/logi-advice.html";
     }
+
+    @GetMapping("/admin")
+    public String admin () {
+        log.info("========== Move to Admin ==========");
+        return HTML_PATH + "admin/login.html";
+    }
+
+    @GetMapping("/admin/backoffice")
+    public String backOffice () {
+        log.info("========== Move to backOffice ==========");
+        return HTML_PATH + "admin/backoffice.html";
+    }
 }

+ 23 - 0
src/main/java/com/example/ili_web/member/controller/MemberController.java

@@ -0,0 +1,23 @@
+package com.example.ili_web.member.controller;
+
+import com.example.ili_web.member.dto.LoginReq;
+import com.example.ili_web.member.service.MemberService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+@Controller
+@Slf4j
+@AllArgsConstructor
+public class MemberController {
+
+    private final MemberService memberService;
+    @PostMapping("/login")
+    public ResponseEntity login (@RequestBody LoginReq req) {
+        return memberService.login(req);
+    }
+}

+ 35 - 0
src/main/java/com/example/ili_web/member/domain/Member.java

@@ -0,0 +1,35 @@
+package com.example.ili_web.member.domain;
+
+import jakarta.persistence.*;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@Entity
+@NoArgsConstructor( access = AccessLevel.PROTECTED)
+@Table(name="MEMBER")
+public class Member {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column
+    private String userId;
+    @Column
+    private String password;
+    @Column
+    private String name;
+    @Column
+    private String email;
+    @Column
+    private String address;
+    @Column
+    private String type;
+    @Column
+    private String useYn;
+    @Column
+    private String regDt;
+    @Column
+    private String upDt;
+}

+ 9 - 0
src/main/java/com/example/ili_web/member/dto/LoginReq.java

@@ -0,0 +1,9 @@
+package com.example.ili_web.member.dto;
+
+import lombok.Data;
+
+@Data
+public class LoginReq {
+    private String id;
+    private String pw;
+}

+ 8 - 0
src/main/java/com/example/ili_web/member/repository/MemberRepository.java

@@ -0,0 +1,8 @@
+package com.example.ili_web.member.repository;
+
+import com.example.ili_web.member.domain.Member;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface MemberRepository extends JpaRepository<Member, Long> {
+    Member findByUserId(String userId);
+}

+ 32 - 0
src/main/java/com/example/ili_web/member/service/MemberService.java

@@ -0,0 +1,32 @@
+package com.example.ili_web.member.service;
+
+import com.example.ili_web.member.domain.Member;
+import com.example.ili_web.member.dto.LoginReq;
+import com.example.ili_web.member.repository.MemberRepository;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+@AllArgsConstructor
+public class MemberService {
+
+    private final MemberRepository repository;
+    private final PasswordEncoder encoder;
+
+    public ResponseEntity<?> login (LoginReq req) {
+        Member member =repository.findByUserId(req.getId());
+        if (member == null) {
+            return ResponseEntity.status(401).body("아이디를 찾을 수 없습니다.");
+        } else {
+            if (encoder.matches(req.getPw(), member.getPassword())) {
+                return ResponseEntity.ok().body("로그인 성공");
+            } else {
+                return ResponseEntity.status(401).body("비밀번호가 틀렸습니다.");
+            }
+        }
+    }
+}

+ 118 - 0
src/main/resources/static/css/backoffice.css

@@ -0,0 +1,118 @@
+body {
+    font-size: .875rem;
+}
+
+.feather {
+    width: 16px;
+    height: 16px;
+    vertical-align: text-bottom;
+}
+
+/*
+ * Sidebar
+ */
+
+.sidebar {
+    position: fixed;
+    top: 0;
+    /* rtl:raw:
+    right: 0;
+    */
+    bottom: 0;
+    /* rtl:remove */
+    left: 0;
+    z-index: 100; /* Behind the navbar */
+    padding: 48px 0 0; /* Height of navbar */
+    box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
+}
+
+@media (max-width: 767.98px) {
+    .sidebar {
+        top: 5rem;
+    }
+}
+
+.sidebar-sticky {
+    position: relative;
+    top: 0;
+    height: calc(100vh - 48px);
+    padding-top: .5rem;
+    overflow-x: hidden;
+    overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
+}
+
+.sidebar .nav-link {
+    font-weight: 500;
+    color: #333;
+}
+
+.sidebar .nav-link .feather {
+    margin-right: 4px;
+    color: #727272;
+}
+
+.sidebar .nav-link.active {
+    color: #2470dc;
+}
+
+.sidebar .nav-link:hover .feather,
+.sidebar .nav-link.active .feather {
+    color: inherit;
+}
+
+.sidebar-heading {
+    font-size: .75rem;
+    text-transform: uppercase;
+}
+
+/*
+ * Navbar
+ */
+
+.navbar-brand {
+    padding-top: .75rem;
+    padding-bottom: .75rem;
+    font-size: 1rem;
+    background-color: rgba(0, 0, 0, .25);
+    box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
+}
+
+.navbar .navbar-toggler {
+    top: .25rem;
+    right: 1rem;
+}
+
+.navbar .form-control {
+    padding: .75rem 1rem;
+    border-width: 0;
+    border-radius: 0;
+}
+
+.form-control-dark {
+    color: #fff;
+    background-color: rgba(255, 255, 255, .1);
+    border-color: rgba(255, 255, 255, .1);
+}
+
+.form-control-dark:focus {
+    border-color: transparent;
+    box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
+}
+
+.bd-placeholder-img {
+    font-size: 1.125rem;
+    text-anchor: middle;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    user-select: none;
+}
+
+@media (min-width: 768px) {
+    .bd-placeholder-img-lg {
+        font-size: 3.5rem;
+    }
+}
+
+.table-responsive {
+    text-align: center;
+}

+ 53 - 0
src/main/resources/static/css/login.css

@@ -0,0 +1,53 @@
+html,
+body {
+    height: 100%;
+}
+
+body {
+    display: flex;
+    align-items: center;
+    padding-top: 40px;
+    padding-bottom: 40px;
+    background-color: #f5f5f5;
+}
+
+.form-signin {
+    width: 100%;
+    max-width: 330px;
+    padding: 15px;
+    margin: auto;
+}
+
+.form-signin .checkbox {
+    font-weight: 400;
+}
+
+.form-signin .form-floating:focus-within {
+    z-index: 2;
+}
+
+.form-signin input[type="email"] {
+    margin-bottom: -1px;
+    border-bottom-right-radius: 0;
+    border-bottom-left-radius: 0;
+}
+
+.form-signin input[type="password"] {
+    margin-bottom: 10px;
+    border-top-left-radius: 0;
+    border-top-right-radius: 0;
+}
+
+.bd-placeholder-img {
+    font-size: 1.125rem;
+    text-anchor: middle;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    user-select: none;
+}
+
+@media (min-width: 768px) {
+    .bd-placeholder-img-lg {
+        font-size: 3.5rem;
+    }
+}

+ 21 - 0
src/main/resources/static/js/admin/adminChangeInner.js

@@ -0,0 +1,21 @@
+async function adminChangeInner(name) {
+    const element = document.getElementById('admin_section');
+    let code = '';
+    let target = '';
+    if (name === 'admin-notice') {
+        code = 'NT';
+        target = 'notice_list_table';
+    }
+    // html 가져오기
+    await axios.get(`/html/admin/${name}.html`)
+        .then(async (res) => {
+            element.innerHTML = res.data;
+            const list = await getList(code, 1);
+            console.log(list);
+            target = document.getElementById(target);
+            adminMakeTable(list.data.dataList, target, code);
+            adminMakePagenation(list.data, code);
+            //clearModal();
+        })
+}
+

+ 11 - 0
src/main/resources/static/js/admin/adminGetData.js

@@ -0,0 +1,11 @@
+async function getList(type, page) {
+    try {
+        return await axios.post('/api/v1/board/list', {type , page, size : 5});
+    } catch (e) {
+
+    }
+}
+
+async function goToDetail(title, userName, regDt, content) {
+    console.log(title);
+}

+ 36 - 0
src/main/resources/static/js/admin/adminMakeHtml.js

@@ -0,0 +1,36 @@
+function adminMakeTable(list, target, code) {
+    let html = '';
+    for (let data of list) {
+        html += '<tr>';
+        html += `<td><a href="javascript:void(0);" onclick="goToDetail('${data.title}', '${data.userName}', '${data.regDt}','${data.content}')">${data.title}</a></td>`;
+        html += `<td>${data.userName}</td>`;
+        html += `<td>${data.type === 'NT' ? '공지' : '안내'}</td>`;
+        html += `<td>${formatDate(data.regDt)}</td>`;
+        html += '</tr>';
+    }
+    target.innerHTML = html;
+}
+
+function adminMakePagenation(data, type) {
+    let paginationHtml = '<ul class="pagination justify-content-center">';
+
+    // Previous 버튼
+    paginationHtml += '<li class="page-item ' + (data.page <= 1 ? 'disabled' : '') + '">';
+    paginationHtml += `<a class="page-link" href="javascript:void(0);" onclick="getList('${type}', '${data.page - 1}')" tabindex="-1">이전</a>`;
+    paginationHtml += '</li>';
+
+    // 페이지 번호
+    for (let i = 1; i <= data.total; i++) {
+        paginationHtml += '<li class="page-item ' + (i === data.page ? 'active' : '') + '">';
+        paginationHtml += `<a class="page-link" href="javascript:void(0);" onclick="getList('${type}', '${i}')">${i}</a>`;
+        paginationHtml += '</li>';
+    }
+
+    // Next 버튼
+    paginationHtml += '<li class="page-item ' + (data.page >= data.total ? 'disabled' : '') + '">';
+    paginationHtml += `<a class="page-link" href="javascript:void(0);" onclick="getList('${type}', '${data.page + 1}')">다음</a>`;
+    paginationHtml += '</li>';
+    paginationHtml += '</ul>';
+
+    document.getElementById('page_tag').innerHTML = paginationHtml;
+}

+ 0 - 0
src/main/resources/static/js/admin/adminNotice.js


+ 17 - 0
src/main/resources/static/js/admin/login.js

@@ -0,0 +1,17 @@
+async function login () {
+    const id = document.getElementById('member_id').value;
+    const pw = document.getElementById('member_password').value;
+    if (id && pw) {
+      await axios.post('login', {id, pw})
+          .then(res => {
+              console.log(res);
+              location.href = '/admin/backoffice';
+          })
+          .catch(error => {
+              alert(error.response.data);
+          })
+    } else {
+        alert('입력된 정보를 확인하세요.')
+    }
+
+}

+ 8 - 0
src/main/resources/static/js/common/dateFormatter.js

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

+ 0 - 0
src/main/resources/static/js/contact/auth-phone.js → src/main/resources/static/js/contact/authPhone.js


+ 0 - 4
src/main/resources/static/js/contact/getList.js

@@ -13,10 +13,6 @@ function goToDetail (title, userName, regDt, content) {
     document.getElementById('nt_content').innerText = content;
 }
 
-function goToAdvice () {
-
-}
-
 document.addEventListener('DOMContentLoaded', async function () {
     await changeInnerAjax('notice');
 });

+ 3 - 4
src/main/resources/static/js/contact/makeHtml.js

@@ -20,21 +20,20 @@ function pagenation (data, type) {
 
     // Previous 버튼
     paginationHtml += '<li class="page-item ' + (data.page <= 1 ? 'disabled' : '') + '">';
-    paginationHtml += `<a class="page-link" href="javascript:void(0);" onclick="getList(${type}, '${data.page - 1}')" tabindex="-1">이전</a>`;
+    paginationHtml += `<a class="page-link" href="javascript:void(0);" onclick="getList('${type}', '${data.page - 1}')" tabindex="-1">이전</a>`;
     paginationHtml += '</li>';
 
     // 페이지 번호
     for (let i = 1; i <= data.total; i++) {
         paginationHtml += '<li class="page-item ' + (i === data.page ? 'active' : '') + '">';
-        paginationHtml += '<a class="page-link" href="javascript:void(0);" onclick="getList(' + i + ')">' + i + '</a>';
+        paginationHtml += `<a class="page-link" href="javascript:void(0);" onclick="getList('${type}', '${i}')">${i}</a>`;
         paginationHtml += '</li>';
     }
 
     // Next 버튼
     paginationHtml += '<li class="page-item ' + (data.page >= data.total ? 'disabled' : '') + '">';
-    paginationHtml += '<a class="page-link" href="javascript:void(0);" onclick="getList(' + (data.page + 1) + ')">다음</a>';
+    paginationHtml += `<a class="page-link" href="javascript:void(0);" onclick="getList('${type}', '${data.page + 1}')">다음</a>`;
     paginationHtml += '</li>';
-
     paginationHtml += '</ul>';
 
     document.getElementById('page_tag').innerHTML = paginationHtml;

+ 11 - 0
src/main/resources/templates/html/admin/admin-notice-detail.html

@@ -0,0 +1,11 @@
+<div class="card">
+    <div class="card-header">
+        게시글 제목
+        <button type="button" class="btn btn-primary">수정</button>
+        <button type="button" class="btn btn-danger">삭제</button>
+    </div>
+    <div class="card-body">
+        <h5 class="card-title">작성자명 - <small>2024-03-12</small></h5>
+        <p class="card-text">게시글 내용이 여기에 들어갑니다. 게시글에 대한 상세한 내용을 추가하세요.</p>
+    </div>
+</div>

+ 130 - 0
src/main/resources/templates/html/admin/admin-notice.html

@@ -0,0 +1,130 @@
+<h2>공지 목록</h2>
+<div class="table-responsive" id="admin_notice_table">
+    <table class="table table-striped table-sm" >
+        <thead>
+        <tr>
+            <th scope="col" >제목</th>
+            <th scope="col">작성자</th>
+            <th scope="col">구분</th>
+            <th scope="col">등록일</th>
+        </tr>
+        </thead>
+        <tbody id="notice_list_table">
+        <tr>
+            <td>1,001</td>
+            <td>random</td>
+            <td>data</td>
+            <td>placeholder</td>
+            <td>text</td>
+        </tr>
+        <tr>
+            <td>1,002</td>
+            <td>placeholder</td>
+            <td>irrelevant</td>
+            <td>visual</td>
+            <td>layout</td>
+        </tr>
+        <tr>
+            <td>1,003</td>
+            <td>data</td>
+            <td>rich</td>
+            <td>dashboard</td>
+            <td>tabular</td>
+        </tr>
+        <tr>
+            <td>1,003</td>
+            <td>information</td>
+            <td>placeholder</td>
+            <td>illustrative</td>
+            <td>data</td>
+        </tr>
+        <tr>
+            <td>1,004</td>
+            <td>text</td>
+            <td>random</td>
+            <td>layout</td>
+            <td>dashboard</td>
+        </tr>
+        <tr>
+            <td>1,005</td>
+            <td>dashboard</td>
+            <td>irrelevant</td>
+            <td>text</td>
+            <td>placeholder</td>
+        </tr>
+        <tr>
+            <td>1,006</td>
+            <td>dashboard</td>
+            <td>illustrative</td>
+            <td>rich</td>
+            <td>data</td>
+        </tr>
+        <tr>
+            <td>1,007</td>
+            <td>placeholder</td>
+            <td>tabular</td>
+            <td>information</td>
+            <td>irrelevant</td>
+        </tr>
+        <tr>
+            <td>1,008</td>
+            <td>random</td>
+            <td>data</td>
+            <td>placeholder</td>
+            <td>text</td>
+        </tr>
+        <tr>
+            <td>1,009</td>
+            <td>placeholder</td>
+            <td>irrelevant</td>
+            <td>visual</td>
+            <td>layout</td>
+        </tr>
+        <tr>
+            <td>1,010</td>
+            <td>data</td>
+            <td>rich</td>
+            <td>dashboard</td>
+            <td>tabular</td>
+        </tr>
+        <tr>
+            <td>1,011</td>
+            <td>information</td>
+            <td>placeholder</td>
+            <td>illustrative</td>
+            <td>data</td>
+        </tr>
+        <tr>
+            <td>1,012</td>
+            <td>text</td>
+            <td>placeholder</td>
+            <td>layout</td>
+            <td>dashboard</td>
+        </tr>
+        <tr>
+            <td>1,013</td>
+            <td>dashboard</td>
+            <td>irrelevant</td>
+            <td>text</td>
+            <td>visual</td>
+        </tr>
+        <tr>
+            <td>1,014</td>
+            <td>dashboard</td>
+            <td>illustrative</td>
+            <td>rich</td>
+            <td>data</td>
+        </tr>
+        <tr>
+            <td>1,015</td>
+            <td>random</td>
+            <td>tabular</td>
+            <td>information</td>
+            <td>text</td>
+        </tr>
+        </tbody>
+    </table>
+    <nav aria-label="Page navigation" id="page_tag">
+
+    </nav>
+</div>

+ 82 - 0
src/main/resources/templates/html/admin/backoffice.html

@@ -0,0 +1,82 @@
+<!doctype html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="description" content="">
+    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
+    <meta name="generator" content="Hugo 0.84.0">
+    <title>관리자</title>
+
+    <link rel="canonical" href="https://getbootstrap.com/docs/5.0/examples/dashboard/">
+
+
+
+    <!-- Bootstrap core CSS -->
+    <link href="../assets/dist/css/bootstrap.min.css" rel="stylesheet">
+
+    <!-- Custom styles for this template -->
+    <link href="/css/backoffice.css" rel="stylesheet">
+    <link href="/css/bootstrap.min.css" rel="stylesheet">
+</head>
+<body>
+
+<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
+    <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">(주)국제종합물류</a>
+    <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
+        <span class="navbar-toggler-icon"></span>
+    </button>
+    <div class="navbar-nav">
+        <div class="nav-item text-nowrap">
+            <a class="nav-link px-3" href="#">로그아웃</a>
+        </div>
+    </div>
+</header>
+
+<div class="container-fluid">
+    <div class="row">
+        <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
+            <div class="position-sticky pt-3">
+                <ul class="nav flex-column">
+                    <li class="nav-item">
+                        <a class="nav-link active" aria-current="page" href="#">
+                            <span data-feather="home"></span>
+                            홈
+                        </a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" href="javascript:void(0);" th:onclick="adminChangeInner('admin-notice')">
+                            <span data-feather="file"></span>
+                            공지 관리
+                        </a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" href="javascript:void(0);" th:onclick="adminChangeInner('admin-advice')">
+                            <span data-feather="shopping-cart"></span>
+                            문의 관리
+                        </a>
+                    </li>
+                </ul>
+            </div>
+        </nav>
+
+        <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
+            <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
+                <h1 class="h2" id="admin_title">관리자 페이지</h1>
+                <div class="btn-toolbar mb-2 mb-md-0">
+                </div>
+            </div>
+            <div class="table-responsive" id="admin_section">
+            </div>
+
+        </main>
+    </div>
+</div>
+<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
+<script src="/js/admin/adminNotice.js"></script>
+<script src="/js/admin/adminGetData.js"></script>
+<script src="/js/admin/adminChangeInner.js"></script>
+<script src="/js/admin/adminMakeHtml.js"></script>
+<script src="/js/common/dateFormatter.js"></script>
+</body>
+</html>

+ 45 - 0
src/main/resources/templates/html/admin/login.html

@@ -0,0 +1,45 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="description" content="">
+    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
+    <meta name="generator" content="Hugo 0.84.0">
+    <title>(주)국제종합물류</title>
+
+    <link rel="canonical" href="https://getbootstrap.com/docs/5.0/examples/sign-in/">
+
+
+
+    <!-- Bootstrap core CSS -->
+    <link href="/css/login.css" rel="stylesheet">
+    <link href="/css/bootstrap.min.css" rel="stylesheet">
+
+</head>
+<body class="text-center">
+
+<main class="form-signin">
+    <form>
+        <img class="mb-4" src="/image/logo.png" alt="" width="200" height="57">
+        <h1 class="h3 mb-3 fw-normal">로그인</h1>
+
+        <div class="form-floating">
+            <input type="email" class="form-control" id="member_id" placeholder="name@example.com">
+            <label for="member_id">아이디</label>
+        </div>
+        <div class="form-floating">
+            <input type="password" class="form-control" id="member_password" placeholder="Password">
+            <label for="member_password">비밀번호</label>
+        </div>
+
+        <div class="checkbox mb-3">
+
+        </div>
+        <button class="w-100 btn btn-lg btn-primary" type="button" onclick="login()">Sign in</button>
+    </form>
+</main>
+</body>
+<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
+<script src="/js/admin/login.js"></script>
+</html>

+ 2 - 3
src/main/resources/templates/html/contact-us.html

@@ -35,14 +35,13 @@
                     <rect fill="#777" height="100%" width="100%"/>
                 </svg>
 
+
                 <div class="container">
                     <div class="carousel-caption">
                         <h1>고객센터</h1>
                         <p>The Master of Global Logistics</p>
                         <p><a class="btn btn-primary" href="javascript:void(0);" th:onclick="changeInnerAjax('notice')">안내/공지</a>
-                            <!--<a class="btn btn-primary" href="javascript:void(0);" th:onclick="changeInnerAjax('estimate')">물류견적</a>-->
                             <a class="btn btn-primary" href="javascript:void(0);" th:onclick="changeInnerAjax('logi-advice')">물류자문</a>
-                            <!--<a class="btn btn-primary" href="javascript:void(0);">무역자문</a>-->
                         </p>
                     </div>
                 </div>
@@ -75,5 +74,5 @@
 <script src="/js/contact/adviceValidation.js"></script>
 <script src="/js/contact/modalControl.js"></script>
 <script src="/js/cookie/cookie-control.js"></script>
-<script src="/js/contact/auth-phone.js"></script>
+<script src="/js/contact/authPhone.js"></script>
 </html>