자바스크립트-프로젝트(edit)

정영찬·2022년 2월 9일
0

자바스크립트

목록 보기
20/21

index의 책 목록중 하나의 항목이 가지고 있는 view 버튼을 클릭 후 책의 상세정보(book)로 들어갔을 때, edit button 을 누르면 나타나는 화면을 구현한다. 원래 가지고 있는 책의 정보를 수정하고 save 버튼을 누르면 변경된채로 , cancel을 누르면 원래 가지고 있던 정보를 그대로 가진 채 이전 화면(book.html)으로 이동한다.

edit.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>My Faborite Books</title>

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />

    <link rel="stylesheet" type="text/css" href="css/edit.css" />
</head>

<body class="bg-light">
    <div class="container">
        <div class="py-5 text-center">
            <h2>Book Save Form</h2>
            <p class="lead">
                Below is an example of a form that stores book information. Each
                required group of forms has a validation status that can be triggered
                by an attempt to submit a form without completing it.
            </p>
        </div>

        <div class="row">
            <div class="col-md-12 order-md-1">
                <h4 class="mb-3">Book Edit</h4>
                <form id="form-edit-book" class="needs-validation" novalidate>
                    <div class="mb-3">
                        <label for="title">Title <span class="text-muted">책 제목</span></label>
                        <input type="text" class="form-control" id="title" placeholder="책 제목을 입력하세요" required />
                    </div>

                    <div class="mb-3">
                        <label for="comment">Comment <span class="text-muted">한 줄 코멘트</span></label>
                        <input type="text" class="form-control" id="message" placeholder="한 줄 감상평을 입력하세요" required />
                    </div>

                    <div class="mb-3">
                        <label for="author">Author <span class="text-muted">글쓴이</span></label>
                        <input type="text" class="form-control" id="author" placeholder="글쓴이를 입력하세요" required />
                    </div>

                    <div class="mb-3">
                        <label for="link">Link <span class="text-muted">링크</span></label>
                        <input type="text" class="form-control" id="url" placeholder="URL 을 입력하세요" required />
                    </div>

                    <hr class="mb-4" />

                    <button class="btn btn-primary btn-lg btn-block" type="submit">
                        Save
                    </button>

                    <button class="btn btn-secondary btn-lg btn-block" id="btn-cancel">
                        Cancel
                    </button>
                </form>
            </div>
        </div>

        <footer class="my-5 pt-5 text-muted text-center text-small">
            <p class="mb-1">&copy; 2019 Marktube</p>
        </footer>
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
        integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous">
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
        integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous">
    </script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
        integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous">
    </script>

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="js/edit.js"></script>
</body>

</html>

edit.js
구현한 메소드
bindLogoutButton() 로그아웃 버튼
getToken 토큰 체크

getUserByToken(token) 토큰으로 서버에서 사용자의 정보 받아오기

getBooks서버에서 책의 정보 받아오기

render(books) 수정된 책의 정보를 화면에 적용시키기
updateBook(bookId) edit.html 에서 입력한 수정 정보를 가져와서 api가 가지고 있던 데이터를 갱신한다.

function getToken() {
    return localStorage.getItem('token');
}

async function getUserByToken(token) {
    try {
        const res = await axios.get('https://api.marktube.tv/v1/me', {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
        return res.data;
    } catch (error) {
        console.log('getUserByToken error', error);
        return null;
    }

}

async function getBooks(bookId) {
    const token = getToken();
    if (token === null) {
        location.assign('/login');
        return null;
    }
    try {
        const res = await axios.get(`https://api.marktube.tv/v1/book/${bookId}`, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
        return res.data; // 책 데이터
    } catch (error) {
        console.log('getBooks error', error);
        return null;
    }
}
async function updateBook(bookId) {
    const titleElement = document.querySelector('#title');
    const messageElement = document.querySelector('#message');
    const authorElement = document.querySelector('#author');
    const urlElement = document.querySelector('#url');

    const title = titleElement.value;
    const message = messageElement.value;
    const author = authorElement.value;
    const url = urlElement.value;

    if (title === "" || message === "" || author === "" || url === "") {
        return;
    }

    const token = getToken();
    if (token === null) {
        location.assign('/login');
        return;
    }

    await axios.patch(`https://api.marktube.tv/v1/book/${bookId}`, {
        title,
        message,
        author,
        url
    }, {
        headers: {
            Authorization: `Bearer ${token}`,
        }
    });
}

function render(books) {
    const titleElement = document.querySelector('#title');
    titleElement.value = books.title;

    const messageElement = document.querySelector('#message');
    messageElement.value = books.message;

    const authorElement = document.querySelector('#author');
    authorElement.value = books.author;

    const urlElement = document.querySelector('#url');
    urlElement.value = books.url;


    const form = document.querySelector("#form-edit-book");
    form.addEventListener('submit', async event => {
        event.preventDefault();
        event.stopPropagation();
        event.target.classList.add('was-validated');


        try {
            await updateBook(books.bookId);
            location.href = `book?id=${books.bookId}`;
        } catch (error) {
            console.log(error);
        }
    });

    const cancelButtonElement = document.querySelector('#btn-cancel');
    cancelButtonElement.addEventListener('click', event => {
        event.preventDefault();
        event.stopPropagation();
        location.assign(`book?id=${books.bookId}`);
    })


}


async function main() {
    // 브라우저에서 id 가져오기
    const bookId = new URL(location.href).searchParams.get('id');
    // 토큰 체크
    const token = getToken();
    if (token === null) {
        location.assign('/login');
        return;
    }
    // 토큰으로 서버에서 나의 정보 받아오기
    const user = await getUserByToken(token);
    if (user === null) {
        localStorage.clear();
        location.assign('/login');
        return;
    }
    console.log(user);
    // 책을 서버에서 받아오기
    const books = await getBooks(bookId);

    if (books === null) {
        alert("서버에서 책 받아오기 실패")
        return;
    }
    console.log(books);

    //받아온 책을 그리기
    render(books);
}
document.addEventListener('DOMContentLoaded', main);

결과 화면

※new URL(location.href).searchParams.?

  • urlSearchParams에 .get('parameterName')은 해당 parameterName으로 조회되는 첫번째 값을 return한다.

프로젝트 종료

한번에 바로 잘 풀리지는 않았고, 코딩을 하는 것보다 오류를 해결하는데 걸리는 시간이 많았던 날도 있었지만, 코딩이라는 것이 오류를 풀어나가는 과정도 굉장히 중요하고 생각한다. 물론 오류가 어디서 나왔고, 어떻게 해결하는지를 찾는 과정은 힘들지만, 가치있는 경험이었다.
입맛에 따라 추가기능을 구현 할 수 있는 수준이 되기 위해선 다른 프로젝트도 구현해보는게 좋을 것 같다. 보람찬 기분이다.

profile
개발자 꿈나무

0개의 댓글

관련 채용 정보