테마선정

https://bootstrapmade.com/mentor-free-education-bootstrap-theme


npx create-react-app frontend-typescript --template typescript

C:\Work\08_Pilot_Project\01_Blog\01_JPA\03_high_thema\02_Mentor


README.md
패키지 설치 목록

더보기
# 설치 패키지 
# 1) 메뉴 라이브러리 설치
npm i react-router-dom
npm i @types/react-router-dom

# 2) 벡엔드 연동 라이브러리 설치
npm i axios

# 3) pre css 컴파일러 : sass
npm i sass

# 4) Material Page component 업그레이드 
# 과거 v4 -> v5 변경 설치
npm i @mui/material @emotion/react @emotion/styled

# 4-1) 소스에서 임포트 사용법 : <Pagination />
import Pagination from '@mui/material/Pagination';

# 5) typescript jquery, jqueryui type 넣기
# 5-1) typescript jquery 사용
npm i --save-dev @types/jquery
npm i --save-dev @types/jqueryui


# 6) npm i aos 설치 === wowjs(날라다니는 lib)
npm i aos
npm i @types/aos

# 6-1) css import : App.tsx
import "aos/dist/aos.css";

# 6-2) js import : main.js
import AOS from "aos";

# 7) npm install typed.js  : npm 설치
# 공홈 : https://mattboldt.github.io/typed.js/ 
npm install typed.js 

# 7-1) import 방법
import Typed from "typed.js";

# 8) PureCounter npm
# 공홈 : https://github.com/srexi/purecounterjs
npm i @srexi/purecounterjs

# 8-1) PureCounter import : main.js
import PureCounter from "@srexi/purecounterjs";

# 공홈 : https://swiperjs.com/get-started#install-from-npm
# 9) npm i swiper
npm i swiper
npm i @types/swiper

# 9-1) js import : main.js
import Swiper from 'swiper';

# 9-2) css import - App.tsx
import 'swiper/css';


# * 외부 라이브러리 타입이 없을 경우 처리 : 타입 설정
# 1) tsconfig.json 파일 - compilerOptions 속성에 아래 추가 : 프로젝트시작위치/types - 이 위치에 타입을 인식하게 하는 경로 설정
"typeRoots": ["./types", "./node_modules/@types"], // 보통 types 폴더를 만들어 타입 정의
# 2) types/외부라이브러리명/index.d.ts 파일 생성 후 아래 추가
declare module '외부라이브러리명';

라이센스

license.txt
0.00MB

 

 


블로그 테마 선정부터 환경 세팅까지는 이전 블로그 보기

[개인메모(설치환경)] - 01_proman_Blog Thema(블로그 테마) 수정 후 & BackEnd(백앤드) 연동


/* eslint-disable */
export default function initMain() {}
더보기
/* C:\Work\08_Pilot_Project\01_Blog\01_JPA\03_high_thema\02_Mentor\frontend-typescript\src\assets\js\main.js */

/**
 * Template Name: Mentor
 * Updated: Sep 18 2023 with Bootstrap v5.3.2
 * Template URL: https://bootstrapmade.com/mentor-free-education-bootstrap-theme/
 * Author: BootstrapMade.com
 * License: https://bootstrapmade.com/license/
 */

// TODO: 생성자 함수 사용 import
// swiper import
import Swiper from "swiper";
// aos import
import AOS from "aos";
// @srexi/purecounterjs import
import PureCounter from "@srexi/purecounterjs";

/* eslint-disable */
export default function initMain() {
  (function () {
    "use strict";

    /**
     * Easy selector helper function
     */
    const select = (el, all = false) => {
      el = el.trim();
      if (all) {
        return [...document.querySelectorAll(el)];
      } else {
        return document.querySelector(el);
      }
    };

    /**
     * Easy event listener function
     */
    const on = (type, el, listener, all = false) => {
      let selectEl = select(el, all);
      if (selectEl) {
        if (all) {
          selectEl.forEach((e) => e.addEventListener(type, listener));
        } else {
          selectEl.addEventListener(type, listener);
        }
      }
    };

    /**
     * Easy on scroll event listener
     */
    const onscroll = (el, listener) => {
      el.addEventListener("scroll", listener);
    };

    /**
     * Back to top button
     */
    let backtotop = select(".back-to-top");
    if (backtotop) {
      const toggleBacktotop = () => {
        if (window.scrollY > 100) {
          backtotop.classList.add("active");
        } else {
          backtotop.classList.remove("active");
        }
      };
      window.addEventListener("load", toggleBacktotop);
      onscroll(document, toggleBacktotop);
    }

    /**
     * Mobile nav toggle
     */
    on("click", ".mobile-nav-toggle", function (e) {
      select("#navbar").classList.toggle("navbar-mobile");
      this.classList.toggle("bi-list");
      this.classList.toggle("bi-x");
    });

    /**
     * Mobile nav dropdowns activate
     */
    on(
      "click",
      ".navbar .dropdown > a",
      function (e) {
        if (select("#navbar").classList.contains("navbar-mobile")) {
          e.preventDefault();
          this.nextElementSibling.classList.toggle("dropdown-active");
        }
      },
      true
    );

    /**
     * Preloader
     */
    let preloader = select("#preloader");
    if (preloader) {
      window.addEventListener("load", () => {
        preloader.remove();
      });
    }

    /**
     * Testimonials slider
     */
    new Swiper(".testimonials-slider", {
      speed: 600,
      loop: true,
      autoplay: {
        delay: 5000,
        disableOnInteraction: false,
      },
      slidesPerView: "auto",
      pagination: {
        el: ".swiper-pagination",
        type: "bullets",
        clickable: true,
      },
      breakpoints: {
        320: {
          slidesPerView: 1,
          spaceBetween: 20,
        },

        1200: {
          slidesPerView: 2,
          spaceBetween: 20,
        },
      },
    });

    /**
     * Animation on scroll
     */
    window.addEventListener("load", () => {
      AOS.init({
        duration: 1000,
        easing: "ease-in-out",
        once: true,
        mirror: false,
      });
    });

    /**
     * Initiate Pure Counter
     */
    new PureCounter();
  })();
}

Home "/"
about
courses

 

trainers
events
pricing
contact


customer dropdown
커스텀 고객 드롭다운 메뉴

더보기
/* C:\Work\08_Pilot_Project\01_Blog\01_JPA\03_high_thema\02_Menhrefr\frontend-typescript\src\components\common\HeaderCom.tsx */
import React from "react";

export default function HeaderCom() {
  return (
    <>
      {/* <!-- ======= Header ======= --> */}
      <header id="header" className="fixed-top">
        <div className="container d-flex align-items-center">
          <h1 className="logo me-auto">
            <a href="/">Mentor</a>
          </h1>
          {/* <!-- Uncomment below if you prefer href use an image logo --> */}
          {/* <!-- <a href="index.html" className="logo me-auto"><img src="assets/img/logo.png" alt="" className="img-fluid"></a>--> */}

          <nav id="navbar" className="navbar order-last order-lg-0">
            <ul>
              <li>
                <a className="active" href="/">
                  Home
                </a>
              </li>

              {/* About 메뉴 */}
              <li>
                <a href="/about">About</a>
              </li>

              {/* Courses 메뉴 */}
              <li>
                <a href="/courses">Courses</a>
              </li>

              {/* Trainers 메뉴 */}
              <li>
                <a href="/trainers">Trainers</a>
              </li>

              {/* Events 메뉴 */}
              <li>
                <a href="/events">Events</a>
              </li>

              {/* Pricing 메뉴 */}
              <li>
                <a href="/pricing">Pricing</a>
              </li>

              {/* customer 메뉴 */}
              <li className="dropdown">
                {/* 대메뉴 시작 */}
                <a href="#">
                  <span>고객</span> <i className="bi bi-chevron-down"></i>
                </a>
                {/* 대메뉴 끝 */}
                {/* 중메뉴 시작 */}
                <ul>
                  {/* 중메뉴 #1 */}
                  <li>
                    <a href="/customer">고객 조회</a>
                  </li>
                  {/* 중메뉴 #2 */}
                  <li>
                    <a href="/add-customer">고객 추가</a>
                  </li>
                </ul>
                {/* 중메뉴 끝 */}
              </li>

              {/* qna 메뉴 */}
              <li className="dropdown">
                {/* 대메뉴 시작 */}
                <a href="#">
                  <span>Q&A</span> <i className="bi bi-chevron-down"></i>
                </a>
                {/* 대메뉴 끝 */}
                {/* 중메뉴 시작 */}
                <ul>
                  {/* 중메뉴 #1 */}
                  <li>
                    <a href="/qna">Q&A 조회</a>
                  </li>
                  {/* 중메뉴 #2 */}
                  <li>
                    <a href="/add-qna">Q&A 추가</a>
                  </li>
                </ul>
                {/* 중메뉴 끝 */}
              </li>

              {/* Contact 메뉴 */}
              <li>
                <a href="/contact">Contact</a>
              </li>
            </ul>
            <i className="bi bi-list mobile-nav-toggle"></i>
          </nav>

          {/* <!-- .navbar --> */}
          <a href="courses.html" className="get-started-btn">
            Get Started
          </a>
        </div>
      </header>
      {/* <!-- End Header --> */}
    </>
  );
}
삭제 메시지 표시 후 강제 페이지 이동 코드
  // 삭제 함수
  const deleteCustomer = () => {
    CustomerService.remove(customer.cid) // 벡엔드로 삭제요청
      .then((response: any) => {
        console.log(response.data);
        // 삭제 메시지 표시
        alert("삭제되었습니다.");
        // 강제 페이지 이동 : 전체조회
        navigate("/customer");
      })
      .catch((e: Error) => {
        console.log(e);
      });
  };

삭제 시 강제 페이지 이동(메시지 x) 코드
  // 삭제 함수
  const deleteCustomer = () => {
    CustomerService.remove(customer.cid) // 벡엔드로 삭제요청
      .then((response: any) => {
        console.log(response.data);
        // 강제 페이지 이동 : 전체조회
        navigate("/customer");
      })
      .catch((e: Error) => {
        console.log(e);
      });
  };

삭제 시 화면에서 메시지 띄워줌(강제 페이지 이동 x) 코드 
  // 삭제 함수
  const deleteCustomer = () => {
    CustomerService.remove(customer.cid) // 벡엔드로 삭제요청
      .then((response: any) => {
        console.log(response.data);
        setMessage("삭제되었습니다.");
      })
      .catch((e: Error) => {
        console.log(e);
      });
  };

화면에 메시지만 보여주고 강제 이동이 안되기 때문에 따로 페이지 이동을 요청해야한다.