[Spring To-do] 프로젝트 준비

Jeskey·2024년 1월 17일

[Spring Legacy] To-do

목록 보기
5/9

📌 테이블 구성

테이블 컬럼
tno : 글 번호
title : 해야 할 일 목록
finished : 일 완료 여부(N,Y)


기능
등록/삭제/완료

Spring legacy는 현재 sts에서 지원이 중단된 프레임워크인 만큼, 본격적인 프로젝트보다는 스프링 부트를 위한 기능 익히기에 중점을 두고 간단한 토이 프로젝트를 만들어보기로 결정했다.

오라클은 boolean 타입을 지원하지 않기 때문에 Finished 컬럼은 True는 "1", False는 "0"인 char 타입으로 설정하기로 했다.

📌 템플릿

🔗 무료 Todo 템플릿 링크

htmlwebapp/WEB-INF/views 폴더에 jsp 파일로,
css, js와 같은 정적 파일은 webapp/resources 폴더 아래에 놓아야 한다.

TodoController를 만들어 제대로 페이지가 뜨는 것을 확인한다.

📂 TodoController.java

@Controller
public class TodoController {
	
	@RequestMapping("/todo")
	public String todoMethod() {
		
		return "todo";
	}
}


📌 정적 파일 코드

style.css

@charset "UTF-8";

body{
    margin-top:20px;
    background: #f8f8f8;
    
}

a {
    color: #007bff;
    text-decoration: none;
    background-color: transparent;
}


.container {
    width: 100%;
    max-width:600px;
    padding-right: 15px;
    padding-left: 15px;
    margin-right: auto;
    margin-left: auto;
}

.todo-nav {
    margin-top: 10px
}

.todo-list {
    margin: 10px 0
}

.todo-list .todo-item {
    padding: 15px;
    margin: 5px 0;
    border-radius: 0;
    background: #f7f7f7
}

.nav {
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    padding-left: 0;
    margin-bottom: 0;
    list-style: none;
}

.nav-pills .nav-link {
    border-radius: 0.25rem;
}

.nav-link {
    display: block;
    padding: 0.5rem 1rem;
}

.todo-list.only-active .todo-item.complete {
    display: none
}

.todo-list.only-active .todo-item:not(.complete) {
    display: block
}

.todo-list.only-complete .todo-item:not(.complete) {
    display: none
}

.todo-list.only-complete .todo-item.complete {
    display: block
}

.todo-list .todo-item.complete span {
    text-decoration: line-through
}

.remove-todo-item {
    color: #000;
    float:right;
    visibility: hidden;
}

.remove-todo-item:hover {
    color: #5f5f5f
}

.todo-item:hover .remove-todo-item {
    visibility: visible
}

div.checker {
    width: 18px;
    height: 18px
}

div.checker input,
div.checker span {
    width: 18px;
    height: 18px
}

div.checker span {
    display: -moz-inline-box;
    display: inline-block;
    zoom: 1;
    text-align: center;
    background-position: 0 -260px;
}

div.checker, div.checker input, div.checker span {
    width: 19px;
    height: 19px;
}

div.checker, div.radio, div.uploader {
    position: relative;
}

div.button, div.button *, div.checker, div.checker *, div.radio, div.radio *, div.selector, div.selector *, div.uploader, div.uploader * {
    margin: 0;
    padding: 0;
}

div.button, div.checker, div.radio, div.selector, div.uploader {
    display: -moz-inline-box;
    display: inline-block;
    zoom: 1;
    vertical-align: middle;
}

.card {
    padding: 25px;
    margin-bottom: 20px;
    border: initial;
    background: #fff;
    border-radius: calc(.15rem - 1px);
    box-shadow: 0 1px 15px rgba(0,0,0,0.04), 0 1px 6px rgba(0,0,0,0.04);
}

.card-body {
    -ms-flex: 1 1 auto;
    flex: 1 1 auto;
    min-height: 1px;
    padding: 1.25rem;
}

.form-control {
    display: block;
    width: 100%;
    height: calc(1.5em + 0.75rem + 2px);
    padding: 0.375rem 0.75rem;
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
    color: #495057;
    background-color: #fff;
    background-clip: padding-box;
    border: 1px solid #ced4da;
    border-radius: 0.25rem;
    transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}

script.js

$( document ).ready(function() {
    
    "use strict";
    
    var todo = function() { 
        $('.todo-list .todo-item input').click(function() {
        if($(this).is(':checked')) {
            $(this).parent().parent().parent().toggleClass('complete');
        } else {
            $(this).parent().parent().parent().toggleClass('complete');
        }
    });
    
    $('.todo-nav .all-task').click(function() {
        $('.todo-list').removeClass('only-active');
        $('.todo-list').removeClass('only-complete');
        $('.todo-nav li.active').removeClass('active');
        $(this).addClass('active');
    });
    
    $('.todo-nav .active-task').click(function() {
        $('.todo-list').removeClass('only-complete');
        $('.todo-list').addClass('only-active');
        $('.todo-nav li.active').removeClass('active');
        $(this).addClass('active');
    });
    
    $('.todo-nav .completed-task').click(function() {
        $('.todo-list').removeClass('only-active');
        $('.todo-list').addClass('only-complete');
        $('.todo-nav li.active').removeClass('active');
        $(this).addClass('active');
    });
    
    $('#uniform-all-complete input').click(function() {
        if($(this).is(':checked')) {
            $('.todo-item .checker span:not(.checked) input').click();
        } else {
            $('.todo-item .checker span.checked input').click();
        }
    });
    
    $('.remove-todo-item').click(function() {
        $(this).parent().remove();
    });
    };
    
    todo();
    
    $(".add-task").keypress(function (e) {
        $(document).on('.todo-list .todo-item.added input').click(function() {
            if($(this).is(':checked')) {
                $(this).parent().parent().parent().toggleClass('complete');
            } else {
                $(this).parent().parent().parent().toggleClass('complete');
            }
        });
        $('.todo-list .todo-item.added .remove-todo-item').click(function() {
            $(this).parent().remove();
        });
    });
}); 

todo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/resources/style.css">
<link
	href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i,700,700i"
	rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
	rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" 
	integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" 
	crossorigin="anonymous" referrerpolicy="no-referrer" />
<title>Insert title here</title>
</head>
<body>
	<div style="position: relative">
		<div class="container">
			<div class="card card-white">
				<div class="card-body">
					<form action="javascript:void(0);">
						<input type="text" class="form-control add-task"
							placeholder="New Task...">
					</form>
					<ul class="nav nav-pills todo-nav">
						<li role="presentation" class="nav-item all-task active"><a
							href="#" class="nav-link">All</a></li>
						<li role="presentation" class="nav-item active-task"><a
							href="#" class="nav-link">Active</a></li>
						<li role="presentation" class="nav-item completed-task"><a
							href="#" class="nav-link">Completed</a></li>
					</ul>
					<div class="todo-list">
						<div class="todo-item jumbotron">
							<div class="checker">
								<span class=""><input type="checkbox"></span>
							</div>
							<span>Create theme</span>
							<a href="javascript:void(0);"
								class="float-right remove-todo-item"><i class="fa-solid fa-xmark"></i></a>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>

	<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
	<script type="text/javascript" src="/resources/script.js"></script>
</body>
</html>

head 태그 안에 css 파일을, /body 태그 바로 위에 script 파일을 불러왔다.

resources 내의 정적 파일을 불러올 때 링크에 /resources/를 포함해야 한다는 걸 잊지 말자.

0개의 댓글