Home.tsx
상세조회 컴포넌트 간에 통신한 상세 조회(props)
// C:\Work\08_Pilot_Project\01_Blog\01_JPA\01_easy_thema\02_creative-gh\frontend-typescript\src\pages\Home.tsx
기본키를 저장 할 변수
const [pid, setPid] = useState<number>(0);
화면 바꿔 보여주기 함수
props : 자식쪽으로 함수(handleChange) 전달
return <DeptList handleChange={handleChange} />;
else if(viewName === "dept") { // props : 자식쪽으로 변수(dno) 전달 return <Dept dno={pid} />
더보기
더보기
// C:\Work\08_Pilot_Project\01_Blog\01_JPA\01_easy_thema\01_stylish-portfolio\frontend-typescript\src\pages\Home.tsx : rfce
import React, { useEffect, useState } from "react";
import initMain from "../assets/js/scripts";
// styles.css import : react 의 최고 부모 컴포넌트 (App.tsx)
import "../assets/css/styles.css";
import DeptList from "./basic/dept/DeptList";
import AddDept from "./basic/dept/AddDept";
import CustomerList from "./basic/customer/CustomerList";
import AddCustomer from "./basic/customer/AddCustomer";
import Dept from "./basic/dept/Dept";
export default function Home() {
// TODO: 바인딩 변수
// 화면명을 저장 할 변수
const [viewName, setViewName] = useState<string>("");
// TODO : 기본키를 저장 할 변수
const [pid, setPid] = useState<number>(0);
// 화면이 뜰 때 실행되는 이벤트
useEffect(() => {
initMain(); // 사이트 메뉴 실행}
}, []);
// todo : 함수 정의
// 버튼 메뉴에 따라 다른 화면 보여주기 함수 : 클릭 이벤트 함수
const handleChange = (viewName: string, pid = 0) => {
setViewName(viewName); // 클릭하면 viewName 변수에 저장(화면에 저장)
setPid(pid); // 기본키 저장
};
// 화면 바꿔 보여주기 함수
const changeView = () => {
if (viewName === "deptList") {
// props : 자식쪽으로 함수(handleChange) 전달
return <DeptList handleChange={handleChange} />;
} else if (viewName === "addDept") {
return <AddDept />;
} else if(viewName === "dept") {
// props : 자식쪽으로 변수(dno) 전달
return <Dept dno={pid} />
} else if (viewName === "customerList") {
return <CustomerList />;
} else if (viewName === "addCustomer") {
return <AddCustomer />;
}
};
return (
// TODO: HTML
<div id="page-top">
{/* <!-- Navigation--> */}
<a className="menu-toggle rounded" href="#">
<i className="fas fa-bars"></i>
</a>
<nav id="sidebar-wrapper">
<ul className="sidebar-nav">
<li className="sidebar-brand">
<a href="#page-top">Start Bootstrap</a>
</li>
<li className="sidebar-nav-item">
<a href="#page-top">Home</a>
</li>
<li className="sidebar-nav-item">
<a href="#about">About</a>
</li>
<li className="sidebar-nav-item">
<a href="#services">Services</a>
</li>
<li className="sidebar-nav-item">
<a href="#portfolio">Portfolio</a>
</li>
<li className="sidebar-nav-item">
<a href="#contact">Contact</a>
</li>
</ul>
</nav>
{/* <!-- Header--> */}
<header className="masthead d-flex align-items-center">
<div className="container px-4 px-lg-5 text-center">
<h1 className="mb-1">Simple Coding</h1>
<h3 className="mb-5">
<em>안녕하세요 저의 블로거에 오신것을 환영합니다.</em>
</h3>
<a className="btn btn-primary btn-xl" href="#about">
Find Out More
</a>
</div>
</header>
{/* <!-- About--> */}
<section className="content-section bg-light" id="about">
<div className="container px-4 px-lg-5 text-center">
<div className="row gx-4 gx-lg-5 justify-content-center">
<div className="col-lg-10">
<h2>
Stylish Portfolio is the perfect theme for your next project!
</h2>
<p className="lead mb-5">
This theme features a flexible, UX friendly sidebar menu and
stock photos from our friends at
<a href="https://unsplash.com/">Unsplash</a>!
</p>
<a className="btn btn-dark btn-xl" href="#services">
What We Offer
</a>
</div>
</div>
</div>
</section>
{/* <!-- Services--> */}
<section
className="content-section bg-primary text-white text-center"
id="services"
>
<div className="container px-4 px-lg-5">
<div className="content-section-heading">
<h3 className="text-secondary mb-0">Services</h3>
<h2 className="mb-5">What We Offer</h2>
</div>
<div className="row gx-4 gx-lg-5">
<div className="col-lg-3 col-md-6 mb-5 mb-lg-0">
<span className="service-icon rounded-circle mx-auto mb-3">
<i className="icon-screen-smartphone"></i>
</span>
<h4>
<strong>Responsive</strong>
</h4>
<p className="text-faded mb-0">Looks great on any screen size!</p>
</div>
<div className="col-lg-3 col-md-6 mb-5 mb-lg-0">
<span className="service-icon rounded-circle mx-auto mb-3">
<i className="icon-pencil"></i>
</span>
<h4>
<strong>Redesigned</strong>
</h4>
<p className="text-faded mb-0">
Freshly redesigned for Bootstrap 5.
</p>
</div>
<div className="col-lg-3 col-md-6 mb-5 mb-md-0">
<span className="service-icon rounded-circle mx-auto mb-3">
<i className="icon-like"></i>
</span>
<h4>
<strong>Favorited</strong>
</h4>
<p className="text-faded mb-0">
Millions of users
<i className="fas fa-heart"></i>
Start Bootstrap!
</p>
</div>
<div className="col-lg-3 col-md-6">
<span className="service-icon rounded-circle mx-auto mb-3">
<i className="icon-mustache"></i>
</span>
<h4>
<strong>Question</strong>
</h4>
<p className="text-faded mb-0">I mustache you a question...</p>
</div>
</div>
</div>
</section>
{/* <!-- Callout--> */}
<section className="callout">
<div className="container px-4 px-lg-5 text-center">
<h2 className="mx-auto mb-5">
Welcome to
<em>your</em>
next website!
</h2>
<a
className="btn btn-primary btn-xl"
href="https://startbootstrap.com/theme/stylish-portfolio/"
>
Download Now!
</a>
</div>
</section>
{/* <!-- Portfolio : 부서/고객 메뉴 -->
*/}
<section className="content-section" id="portfolio">
<div className="container px-4 px-lg-5">
<div className="content-section-heading text-center">
<h3 className="text-secondary mb-0">Portfolio</h3>
<h2 className="mb-5">Recent Projects</h2>
</div>
{/* 부서 시작 */}
<div className="row gx-0">
<div className="col-lg-6">
<a className="portfolio-item" href="#!">
<div className="caption">
<div className="caption-content">
<div className="h2">Department 예제</div>
<p className="mb-0">
부서게시판을 만들면서 <br />
React & Springboot & Oracle 연동하기
</p>
<span
className="badge text-bg-success"
onClick={() => handleChange("deptList")}
>
Department 조회
</span>
<span
className="badge text-bg-danger"
onClick={() => handleChange("addDept")}
>
Department 추가
</span>
</div>
</div>
<img
className="img-fluid"
src="assets/img/portfolio-1.jpg"
alt="..."
/>
</a>
</div>
{/* 부서 끝 */}
{/* 고객 시작 */}
<div className="col-lg-6">
<a className="portfolio-item" href="#!">
<div className="caption">
<div className="caption-content">
<div className="h2">Customer 예제</div>
<p className="mb-0">
Customer 게시판을 만들면서 <br />
React & Springboot & Oracle 연동 예제 2
</p>
{/* 버튼 메뉴 시작 */}
<span
className="badge text-bg-warning"
onClick={() => handleChange("customerList")}
>
Customer 조회
</span>
<span
className="badge text-bg-info"
onClick={() => handleChange("addCustomer")}
>
Customer 추가
</span>
{/* 버튼 메뉴 끝 */}
</div>
</div>
<img
className="img-fluid"
src="assets/img/portfolio-2.jpg"
alt="..."
/>
</a>
</div>
{/* 고객 끝 */}
<div className="col-lg-6">
<a className="portfolio-item" href="#!">
<div className="caption">
<div className="caption-content">
<div className="h2">Strawberries</div>
<p className="mb-0">
Strawberries are such a tasty snack, especially with a
little sugar on top!
</p>
</div>
</div>
<img
className="img-fluid"
src="assets/img/portfolio-3.jpg"
alt="..."
/>
</a>
</div>
<div className="col-lg-6">
<a className="portfolio-item" href="#!">
<div className="caption">
<div className="caption-content">
<div className="h2">Workspace</div>
<p className="mb-0">
A yellow workspace with some scissors, pencils, and other
objects.
</p>
</div>
</div>
<img
className="img-fluid"
src="assets/img/portfolio-4.jpg"
alt="..."
/>
</a>
</div>
</div>
</div>
</section>
{/* TODO: 여기 */}
{/* <!-- Portfolio - result : 부서/고객 결과 --> */}
<section className="content-section" id="portfolio">
<div className="container px-4 px-lg-5">
{/* 제목 시작 */}
<div className="content-section-heading text-center">
<h3 className="text-secondary mb-0">맛보기 샘플 - 결과</h3>
<h2 className="mb-5">Recent Result</h2>
</div>
{/* 제목 끝 */}
{/* 게시판 결과 시작 */}
<div className="row gx-0">
<div className="col-lg-12">{changeView()}</div>
</div>
{/* 게시판 결과 끝 */}
</div>
</section>
{/* <!-- Call to Action--> */}
<section className="content-section bg-primary text-white">
<div className="container px-4 px-lg-5 text-center">
<h2 className="mb-4">
The buttons below are impossible to resist...
</h2>
<a className="btn btn-xl btn-light me-4" href="#!">
Click Me!
</a>
<a className="btn btn-xl btn-dark" href="#!">
Look at Me!
</a>
</div>
</section>
{/* <!-- Map--> */}
<div className="map" id="contact">
<iframe src="https://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=Twitter,+Inc.,+Market+Street,+San+Francisco,+CA&aq=0&oq=twitter&sll=28.659344,-81.187888&sspn=0.128789,0.264187&ie=UTF8&hq=Twitter,+Inc.,+Market+Street,+San+Francisco,+CA&t=m&z=15&iwloc=A&output=embed"></iframe>
<br />
<small>
<a href="https://maps.google.com/maps?f=q&source=embed&hl=en&geocode=&q=Twitter,+Inc.,+Market+Street,+San+Francisco,+CA&aq=0&oq=twitter&sll=28.659344,-81.187888&sspn=0.128789,0.264187&ie=UTF8&hq=Twitter,+Inc.,+Market+Street,+San+Francisco,+CA&t=m&z=15&iwloc=A"></a>
</small>
</div>
{/* <!-- Footer--> */}
<footer className="footer text-center">
<div className="container px-4 px-lg-5">
<ul className="list-inline mb-5">
<li className="list-inline-item">
<a
className="social-link rounded-circle text-white mr-3"
href="#!"
>
<i className="icon-social-facebook"></i>
</a>
</li>
<li className="list-inline-item">
<a
className="social-link rounded-circle text-white mr-3"
href="#!"
>
<i className="icon-social-twitter"></i>
</a>
</li>
<li className="list-inline-item">
<a className="social-link rounded-circle text-white" href="#!">
<i className="icon-social-github"></i>
</a>
</li>
</ul>
<p className="text-muted small mb-0">
Copyright © Your Website 2023
</p>
</div>
</footer>
{/* <!-- Scroll to Top Button--> */}
<a className="scroll-to-top rounded" href="#page-top">
<i className="fas fa-angle-up"></i>
</a>
{/* <!-- Bootstrap core JS--> */}
{/* <!-- Core theme JS--> */}
</div>
);
}
Dept.tsx
// C:\Work\08_Pilot_Project\01_Blog\01_JPA\01_easy_thema\01_stylish-portfolio\frontend-typescript\src\pages\basic\dept\Dept.tsx
더보기
더보기
// C:\Work\08_Pilot_Project\01_Blog\01_JPA\01_easy_thema\01_stylish-portfolio\frontend-typescript\src\pages\basic\dept\Dept.tsx : rfce
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import IDept from "../../../types/basic/IDept";
import DeptService from "../../../service/basic/DeptService";
import TitleCom from '../../../components/common/TitleCom';
function Dept(props: any) {
// TODO: 변수 정의
// 전체조회 페이지에서 전송한 기본키(dno)
// TODO : const { dno } = useParams();
const dno = props.dno;
// 강제페이지 이동 함수
let navigate = useNavigate();
// 객체 초기화(상세조회 : 기본키 있음)
const initialDept = {
dno: "",
dname: "",
loc: "",
};
// 수정 될 객체
const [dept, setDept] = useState<IDept>(initialDept);
// 화면에 수정 성공에 메세지 찍기 변수
const [message, setMessage] = useState<string>("");
// TODO: 함수 정의
// 상세조회 함수
const getDept = (dno: string) => {
DeptService.get(dno) // 벡엔드로 상세조회 요청
.then((response: any) => {
setDept(response.data);
console.log(response.data);
})
.catch((e: Error) => {
console.log(e);
});
};
// 화면이 뜰때 실행되는 이벤트 + dno 값이 바뀌면 실행
useEffect(() => {
if (dno) getDept(dno);
}, [dno]);
// input 태그 수동 바인딩
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
setDept({ ...dept, [name]: value });
};
// 수정 함수
const updateDept = () => {
DeptService.update(dept.dno, dept) // 벡엔드로 수정요청
.then((response: any) => {
console.log(response.data);
setMessage("The dept was updated successfully!");
})
.catch((e: Error) => {
console.log(e);
});
};
// 삭제 함수
const deleteDept = () => {
DeptService.remove(dept.dno) // 벡엔드로 삭제요청
.then((response: any) => {
console.log(response.data);
// TODO : 페이지 이동 메시지로 전달 수정
// navigate("/dept");
setMessage("삭제되었습니다.");
})
.catch((e: Error) => {
console.log(e);
});
};
return (
// TODO: JSX
<>
{/* 제목 start */}
<TitleCom title="Dept Detail" />
{/* 제목 end */}
<>
{dept ? (
<div className="col-6 mx-auto">
<form>
<div className="row g-3 align-items-center mb-3">
<div className="col-3">
<label htmlFor="dname" className="col-form-label">
Dname
</label>
</div>
<div className="col-9">
<input
type="text"
id="dname"
required
className="form-control"
value={dept.dname}
onChange={handleInputChange}
placeholder="dname"
name="dname"
/>
</div>
</div>
<div className="row g-3 align-items-center mb-3">
<div className="col-3">
<label htmlFor="loc" className="col-form-label">
Loc
</label>
</div>
<div className="col-9">
<input
type="text"
id="loc"
required
className="form-control"
value={dept.loc}
onChange={handleInputChange}
placeholder="loc"
name="loc"
/>
</div>
</div>
</form>
<div className="row g-3 mt-3 mb-3">
<button
onClick={deleteDept}
className="btn btn-outline-danger ms-3 col"
>
Delete
</button>
<button
type="submit"
onClick={updateDept}
className="btn btn-outline-success ms-2 col"
>
Update
</button>
</div>
{message && (
<p className="alert alert-success mt-3 text-center">{message}</p>
)}
</div>
) : (
<div className="col-6 mx-auto">
<br />
<p>Please click on a Dept...</p>
</div>
)}
</>
</>
);
}
export default Dept;
DeptList.tsx
// C:\Work\08_Pilot_Project\01_Blog\01_JPA\01_easy_thema\01_stylish-portfolio\frontend-typescript\src\pages\basic\dept\DeptList.tsx
더보기
더보기
// C:\Work\08_Pilot_Project\01_Blog\01_JPA\01_easy_thema\01_stylish-portfolio\frontend-typescript\src\pages\basic\dept\DeptList.tsx : rfce
// 전체조회페이지 + 페이징
import { Pagination } from "@mui/material";
import { Link } from "react-router-dom";
import { useState, useEffect } from "react";
import IDept from "../../../types/basic/IDept";
import DeptService from "../../../service/basic/DeptService";
import TitleCom from "../../../components/common/TitleCom";
function DeptList(props: any) {
// TODO: 변수 정의
// 부서 배열 변수
const [dept, setDept] = useState<Array<IDept>>([]);
// 검색어 변수
const [searchDname, setSearchDname] = useState<string>("");
// 공통 변수 : page(현재페이지번호), count(총페이지건수), pageSize(3,6,9 배열)
const [page, setPage] = useState<number>(1);
const [count, setCount] = useState<number>(1);
const [pageSize, setPageSize] = useState<number>(3); // 1페이지당개수
// pageSizes : 배열 (셀렉트 박스 사용)
const pageSizes = [3, 6, 9];
// TODO: 함수 정의
// TODO : 1) 컴포넌트가 mounted 될때 한번만 실행됨 : useEffect(() => {실행문},[])
// TODO : 2) 컴포넌트의 변수값이 변할때 실행됨 : useEffect(() => {실행문},[감시변수])
useEffect(() => {
retrieveDept(); // 전체 조회
}, [page, pageSize]);
// 전체조회 함수
const retrieveDept = () => {
// TODO : 벡엔드 매개변수 전송 : + 현재페이지(page), 1페이지당개수(pageSize)
DeptService.getAll(searchDname, page - 1, pageSize) // 벡엔드 전체조회요청
.then((response: any) => {
// 벡엔드 성공시 실행됨
// es6(모던js) 문법 : 객체 분해 할당
// const dept = response.data.dept; // 부서배열
// const totalPages = response.data.totalPages; // 전체페이지수
const { dept, totalPages } = response.data;
// dept 저장
setDept(dept);
setCount(totalPages);
// 로그 출력
console.log("response", response.data);
})
.catch((e: Error) => {
// 벡엔드 실패시 실행됨
console.log(e);
});
};
// 검색어 수동 바인딩 함수
const onChangeSearchDname = (e: any) => {
const searchDname = e.target.value;
setSearchDname(searchDname);
};
// TODO : handlePageSizeChange : pageSize 값 변경시 실행되는 함수
// select 태그 수동 바인딩 : 화면값 -> 변수에 저장
const handlePageSizeChange = (event: any) => {
setPageSize(event.target.value); // 1페이지당 개수저장(3,6,9)
setPage(1); // 현재페이지번호 : 1로 강제설정
};
// TODO : Pagination 수동 바인딩
// 페이지 번호를 누르면 => page 변수에 값 저장
const handlePageChange = (event: any, value: number) => {
// value == 화면의 페이지번호
setPage(value);
};
return (
// TODO: JSX
<>
{/* 제목 start */}
<TitleCom title="Dept List" />
{/* 제목 end */}
{/* dname start */}
<div className="row mb-5 justify-content-center">
{/* w-50 : 크기 조정, mx-auto : 중앙정렬(margin: 0 auto), justify-content-center */}
<div className="col-12 w-50 input-group mb-3">
<input
type="text"
className="form-control"
placeholder="Search by dname"
value={searchDname}
onChange={onChangeSearchDname}
/>
<div className="input-group-append">
<button
className="btn btn-outline-secondary"
type="button"
onClick={retrieveDept}
>
Search
</button>
</div>
</div>
</div>
{/* dname end */}
{/* paging 시작 */}
<div className="mt-3">
{"Items per Page: "}
<select onChange={handlePageSizeChange} value={pageSize}>
{pageSizes.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
{/* TODO: 사용법 : count={1페이지당개수} , page={현재페이지번호} */}
<Pagination
className="my-3"
count={count}
page={page}
siblingCount={1}
boundaryCount={1}
variant="outlined"
shape="rounded"
onChange={handlePageChange}
/>
</div>
{/* paging 끝 */}
{/* table start */}
<div className="col-md-12">
{/* table start */}
<table className="table">
<thead className="table-light">
<tr>
<th scope="col">Dname</th>
<th scope="col">Loc</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{dept &&
dept.map((data) => (
<tr key={data.dno}>
<td>{data.dname}</td>
<td>{data.loc}</td>
<td>
{/* TODO: 소스 코칠 부분 : 컴포넌트 통신을 사용하는 방법(링크를 사용 할 수 없기 떄문에 props. dno 상세조회 시키기) */}
<Link to="#">
<span className="badge bg-success"
onClick={()=>props.handleChange("dept", data.dno)}
>Edit</span>
</Link>
</td>
</tr>
))}
</tbody>
</table>
{/* table end */}
</div>
{/* table end */}
</>
);
}
export default DeptList;
'Spring Boot' 카테고리의 다른 글
02_prixima_Blog Thema(블로그 테마) 수정 후 & BackEnd(백앤드) 연동 (1) | 2023.11.02 |
---|---|
01_proman_Blog Thema(블로그 테마) 수정 후 & BackEnd(백앤드) 연동 (0) | 2023.11.01 |
Blog Thema(블로그 테마) & BackEnd(백앤드) 연동 (0) | 2023.11.01 |
02_creative-gh easy_Blog Thema(블로그 테마) 연습 예제 (1) | 2023.10.31 |
01_stylish-portfolio easy_Blog Thema(블로그 테마) (0) | 2023.10.31 |