본문 바로가기

Server Programming/Spring Boot Full-Stack Programming

[스프링 풀스택 클론 코딩 - 회원가입] (1-14) 뷰 중복 코드 제거

반응형

 

fragments

<!DOCTYPE html>
<!-- fragment 뷰 -> 자주 사용하는 조각ㅁ-->
<!-- 타임리프 네임스페이스 설정-->
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

<head th:fragment="head">
	<meta charset="UTF-8">
	<title>Demo</title>
	<!-- CSS only-> npm으로 이전
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet"
		integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
		-->
	<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css" />
	<style>
		.container {
			max-width: 100%;
		}
	</style>
</head>
	<!-- 네비바 만들기-->
	<nav th:fragment="main-nav" class="navbar navbar-expand-sm navbar-dark bg-dark">

		<!-- 배너-->
		<a class="navbar-brand" href="/" th:href="@{/}">
			<!--@는 경로설정인데 이 경우엔 root경로 -->
			<img src="/images/logo_sm.png" width="30" height="30">
		</a>

		<!-- 네비게이션 아이템 검색 창-->
		<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent">
			<span class="navbar-toggler-icon"> </span>
		</button>

		<div class="collapse navbar-collapse" id="navbarSupportedContent">
			<ul class="navbar-nav mr-auto">
				<li class="nav-item">
					<!-- 스터디 찾기 버튼 href="#" th:href="은 타임리프 동작 X와 동작시-->
					<form th:action="@{/search/study}" class="form-inline" method="get" action="#">
						<input class="form-control mr-sm-2" name="keyword" placeholder="스터디 찾기" type="search" />
					</form>
				</li>
			</ul>
			<!-- 로그인, 가입 버튼 href="#" th:href="은 타임리프 동작 X와 동작시-->
			<ul class="navbar-nav justify-content-end">
				<li class="nav-item" sec:authorize="!isAuthenticated()">
					<a class="nav-link" th:href="@{/login}">로그인</a>
				</li>
				<li class="nav-item" sec:authorize="!isAuthenticated()">
					<a class="nav-link" th:href="@{/sign-up}">가입</a>
				</li>
				<li class="nav-item" sec:authorize="isAuthenticated()">
					<a class="nav-link" th:href="@{/notifications}">
						알림
					</a>
				</li>
				<li class="nav-item" sec:authorize="isAuthenticated()">
					<a class="nav-link btn btn-outline-primary" th:href="@{/new-study}">
						스터디 개설
					</a>
				</li>
				<li class="nav-item dropdown" sec:authorize="isAuthenticated()">
					<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
						aria-expanded="false">
						프로필
					</a>
					<div class="dropdown-menu dropdown-menu-sm-right" aria-labelledby="userDropdown">
						<ul>
							<h6 class="dropdown-header">
								<span sec:authentication="name">Username</span>
							</h6>
							<a class="dropdown-item" th:href="@{'/profile/' + ${#authentication.name}}">프로필</a>
							<a class="dropdown-item">스터디</a>
							<div class="dropdown-divider"></div>
							<a class="dropdown-item" th:href="@{'/settings/profile'}">설정</a>
							<form class="form-inline my-2 my-lg-0" action="#" th:action="@{/logout}" method="post">
								<button class="dropdown-item" type="submit">로그아웃</button>
							</form>
						</ul>
					</div>
				</li>
			</ul>
		</div>
	</nav>
	
	<footer th:fragment="footer">
			<div class="row justify-content-center">
				<img class="mb-2" src="/images/logo_long_kr.jpg" alt="" width="100">
				<small class="d-block mb-3 text-muted">&copy; 2020</small>
			</div>
		</footer>
</html>

 

index

<!DOCTYPE html>
<!-- 회원가입 뷰 -> sign-up form을 만들어야 한다. 닉네임 이메일 비밀번호-->
<!-- 타임리프 네임스페이스 설정-->
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

<!-- replace를 이용해 교체-->

<head th:replace="fragments.html :: head"> </head>

<body class="bg-light">
	<div th:replace="fragments.html :: main-nav"></div>

	<!-- index html-->
	<div class="container">
		<div class="py-5 text-center">
			<h2>데모</h2>
		</div>


		<div th:replace="fragments.html :: footer"></div>
	</div>


	<!--npm 으로 이전
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
		integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
		crossorigin="anonymous">
		-->

	<script src="/node_modules/jquery/dist/jquery.min.js"></script>
	<script src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>

	</script>

	<!--needs-validation을 가지는 폼을 가져와 submit 이벤트 발생시 유효여부 검증, 유효하지 않으면, submit안되도록 처리 -->
	<!--유효하면 was-validated에 추가 -> input의 required을 기반으로 처리-->
	<script type="application/javascript" th:fragment="form-validation">

	</script>

</body>

</html>

 

sign-up

<!DOCTYPE html>
<!-- 회원가입 뷰 -> sign-up form을 만들어야 한다. 닉네임 이메일 비밀번호-->
<!-- 타임리프 네임스페이스 설정-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head th:replace="fragments.html :: head">

</head>

<body class="bg-light">
	<div th:replace="fragments.html :: main-nav"></div>
	
	<!-- 계정만들기 sign-up html-->
	<div class="container">
		<div class="py-5 text-center">
			<h2>계정 만들기</h2>
		</div>

		<div class="row justify-content-center">
			<!--th:object="${signUpForm}" 객체 이용해 form을 채운다 -> 객체의 프로퍼티를 *를 이용해 사용-->
			<!--needs-validation 은 html로 검증 -->
			<form class="needs-validation col-sm-6" action="#" th:action="@{/sign-up}" th:object="${signUpForm}"
				method="post" novalidate>
<div class="form-group">
					<label for="nickname">닉네임</label>
					<!-- 필수 : 닉네임 이메일(이메일 형태 검증), 비밀번호 - > 검증이 안되면 invalid-feedback -->
					<input id="nickname" type="text" th:field="*{nickname}" class="form-control" placeholder="whiteship"
						aria-describedby="nicknameHelp" required minlength="3" maxlength="20">

					<small id="nicknameHelp" class="form-text text-muted">
						공백없이 문자와 숫자로만 3자 이상 20자 이내로 입력하세요. 가입후에 변경할 수 있습니다.
					</small>
					<small class="invalid-feedback">닉네임을 입력하세요.</small>
					<small class="form-text text-danger" th:if="${#fields.hasErrors('nickname')}"
						th:errors="*{nickname}">Nickname Error</small>
				</div>

				<div class="form-group">
					<label for="email">이메일</label>
					<input id="email" type="email" th:field="*{email}" class="form-control" placeholder="your@email.com"
						aria-describedby="emailHelp" required>
					<small id="emailHelp" class="form-text text-muted">
						스터디올래는 사용자의 이메일을 공개하지 않습니다.
					</small>
					<small class="invalid-feedback">이메일을 입력하세요.</small>
					<small class="form-text text-danger" th:if="${#fields.hasErrors('email')}"
						th:errors="*{email}">Email Error</small>
				</div>

				<div class="form-group">
					<label for="password">패스워드</label>
					<input id="password" type="password" th:field="*{password}" class="form-control"
						aria-describedby="passwordHelp" required minlength="8" maxlength="50">
					<small id="passwordHelp" class="form-text text-muted">
						8자 이상 50자 이내로 입력하세요. 영문자, 숫자, 특수기호를 사용할 수 있으며 공백은 사용할 수 없습니다.
					</small>
					<small class="invalid-feedback">패스워드를 입력하세요.</small>
					<small class="form-text text-danger" th:if="${#fields.hasErrors('password')}"
						th:errors="*{password}">Password Error</small>
				</div>

				<div class="form-group">
					<button class="btn btn-primary btn-block" type="submit" aria-describedby="submitHelp">가입하기</button>
					<small id="submitHelp" class="form-text text-muted">
						<a href="#">약관</a>에 동의하시면 가입하기 버튼을 클릭하세요.
					</small>

				</div>
			</form>
		</div>
		
	<div th:replace="fragments.html :: footer"></div>
	
		</div>

	
	<!-- JavaScript Bundle with Popper -->
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
		integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
		crossorigin="anonymous"></script>

	<!--needs-validation을 가지는 폼을 가져와 submit 이벤트 발생시 유효여부 검증, 유효하지 않으면, submit안되도록 처리 -->
	<!--유효하면 was-validated에 추가 -> input의 required을 기반으로 처리-->
	<script type="application/javascript" th:fragment="form-validation">
		(function () {
			'use strict';

			window.addEventListener('load', function () {
				// Fetch all the forms we want to apply custom Bootstrap validation styles to
				var forms = document.getElementsByClassName('needs-validation');

				// Loop over them and prevent submission
				Array.prototype.filter.call(forms, function (form) {
					form.addEventListener('submit', function (event) {
						if (form.checkValidity() === false) {
							event.preventDefault();
							event.stopPropagation();
						}
						form.classList.add('was-validated')
					}, false)
				})
			}, false)
		}())
	</script>

</body>

</html>

 

checked-email

<!DOCTYPE html>
<html>

<head th:replace="fragments.html :: head"></div>

</head>

<body class="bg-light">

	    	<div th:replace="fragments.html :: main-nav"></div>
	
	 <div class="py-5 text-center" th:if="${error}">
        <p class="lead">데모 이메일 확인</p>
        <div class="alert alert-danger" role="alert">
            이메일 확인 링크가 정확하지 않습니다.
        </div>
    </div>

    <div class="py-5 text-center" th:if="${error == null}">
        <p class="lead">데모 이메일 확인</p>
        <h2>
           이메일을 확인했습니다. <span th:text="${numberOfUser}">10</span>번째 회원,
            <span th:text="${nickname}">***</span>님 가입을 축하합니다.
        </h2>
        <small class="text-info">이제부터 가입할 때 사용한 이메일 또는 닉네임과 패스트워드로 로그인 할 수 있습니다.</small>
    </div>
    	<div th:replace="fragments.html :: footer"></div>
    
</body>

</html>
반응형