본문 바로가기
풀스택 개발 학습 과정/프론트엔드

[자바스크립트] (예제) 배달음식 주문 예제

by 육츠 2024. 3. 10.
Contents 접기

요구사항

- 기능

- changeTime() 함수 : 현재 시간 = 프로그램이 시작된 시간을 기준으로 1초마다 시간이 업데이트 되도록
- confirmEvent() 함수 : 코드 내의 menulist 변수와, menuqty 변수에 값을 변경했을 때 계산할 수 있도록 이벤트 걸기
-calcPrice() 함수: 각 음식의 주문 수량을 변경했을 때 계산하는 함수
- orderCheck() 함수 : 주문하기 버튼을 클릭했을 때 사용자 입력검증
    ∘ 주문자 이름: 주문자 이름은 반드시 입력 받기,  만약 입력 받지 않을 경우 "주문자 이름을 입력해 주세요" 라는 경고창 띄우기
    ∘ 전화번호: 숫자 11 자리로 입력 받기, 그렇지 않으면 "전화번호는 11 자리 숫자로 입력해 주세요" 라는 경고창 띄우고 전화번호에 포커스 
    ∘ 주소: 주소는 반드시 입력 받기, 그렇지 않으면 "주문자 주소를 입력해 주세요" 라는 경고창을 띄우고 주소에 포커스
- orderCreate() 함수: 주문하기 버튼 클릭 시 지금까지 입력한 정보를 경고창으로 출력되도록
    ∘ 야식메뉴는 메뉴 중 1 가지 이상 선택해야 하며 아무것도 선택하지 않을 경우 "선택된 메뉴가 없습니다." 라는 경고창
    ∘ 최종 경고창의 “확인”버튼을 클릭하면 모든 입력상자의 내용이 초기화

- 디자인

- 전체 글꼴은 임의의 구글 폰트 사용
- 배경색 임의로 지정, 가로 450px 임의의 그림을 다운받아 폴더에 저장한 후 HTML 문서 위치에 표시
타이틀 글자색 임의로 지정
주문하기 버튼과 주문 최소 버튼의 테두리는 둥글게
주문하기 버튼과 주문 최소 버튼에 마우스를 올리면 글자는 두껍게, 테두리 그림자 생성

 

* 해당 예제는 빈칸을 뚫어놓은 부분을 채우는 식으로 사용됐다.

구현내용

Javascript

 

전역 변수 선언, 메뉴명과 가격 가져오기, 함수 선언

// 전역변수 선언
let i = 0;
let totalPrice = 0;     // 총 음식값

setInterval(changeTime, 1000);
let menulist = document.getElementsByName("food");
let menuqty = document.getElementsByClassName("menuqty");
// 개수가 배열이다

confirmEvent();  // 각 메뉴에 주문 수를 입력 시 이벤트 거는 함수

 

닫힌 태그가 아니라면 .value를 사용하여 문서에 넣는다.

// 시간 변경하는 함수 :  // Code Here
function changeTime() {
    let today = new Date();
    let hour  = today.getHours();       // 시간
    let minute  = today.getMinutes();   // 분
    let second  = today.getSeconds();   // 초

    let now = `${hour}시 ${minute}분 ${second}초`;
    let currTime = document.getElementById('currTime');

    currTime.value = now;

}

 

메뉴가 선택되거나 수량을 변경했을때 읽어도록 event로 'keyup 설정'

// 메뉴가 선택되거나 수량을 변경했을 때 계산할 수 있도록 각 8개의 데이터에 이벤트 걸기
function confirmEvent() {
    for (let j = 0; j < menulist.length; j++) {
        // Code here
        menuqty[j].addEventListener('keyup', calcPrice);
        menulist[j].addEventListener('click', calcPrice); // 생략해도 됨
    }
}

 

// 각 음식의 주문 수량을 변경했을 때 계산하는 함수 : Code Here
function calcPrice() {
    let tax = document.getElementById("tax") ;
    let tip = document.getElementById("tip") ;
    let total = document.getElementById("total") ; // total = 음식값 + 세금 + 봉사료
    let menu = this.id;

    // 수량을 0을 만들면 다시 체크박스가 해제되어야함
    if(this.value != 0) 
        document.getElementsByClassName(menu)[0].checked = true;
    else 
        document.getElementsByClassName(menu)[0].checked = false;

    // 수량이 수정되면! 전체 수량을 다시 읽어옴
    totalPrice = 0;
    for(let i=0; i<menulist.length; ++i) {
        if(document.getElementsByName("food")[i].checked) {
            // 선택한 (check된) 데이터의 value값을 이용하여 음식값을 조회
            let price = this.previousSibling.previousSibling.querySelector('input').value;
            let ea = this.value;         // 주문 수량 가져옴
            
            totalPrice += ea*price;
        }
    }
    // 세금은 음식값 2%, 봉사료 음식값 5%을 계산하여 total 영역에 입력.
    tax.value = totalPrice * 0.02;
    tip.value = totalPrice * 0.05;

    total.value = totalPrice + (totalPrice * 0.02) + (totalPrice * 0.05);
}
코드 내용
let price = this.previousSibling.previousSibling.querySelector('input').value; previousSibling URL



sibling node = 형제 노드 

 

주문하기 버튼을 누르면 orderCheck 함수 실행된다.

document.getElementById("order").onclick = orderCheck;

 

이름, 전화번호, 주소 검증 (주소는 우선 받는 것만)

// 주문하기를 클릭했을 때 사용자 입력 검증 및 나머지 작업 수행
function orderCheck() {
    // Code Here: 주문자의 이름, 전화번호, 주소 입력되었는지 확인
    let name = document.getElementById('name');
    let phone = document.getElementById('phone');
    let addr = document.getElementById('address');

    if(name.value.trim().length == 0){
        alert('이름을 입력해주세요')
        name.focus();
        return;
    }

    if(phone.value.trim().length != 11 || isNaN(phone.value)){
        alert('전화번호를 올바르게 입력해주세요')
        phone.select();
        return;
    }

    if(addr.value.trim().length == 0){
        alert('주소를 입력해주세요')
        name.select();
        return;
    }
        // 0 이면 선택
    orderCreate();
}

 

// 최종 주문을 완료함수
function orderCreate() {
    // Code Here
    let orderTime = document.getElementById('currTime').value;
    let name      = document.getElementById('name').value;
    let phone     = document.getElementById('phone').value;
    let address   = document.getElementById('address').value;
    let tax       = document.getElementById('tax').value;
    let tip       = document.getElementById('tip').value;
    let total     = document.getElementById('total').value;

    let bill = `
    * 주문자 : ${name}
    * 연락처 : ${phone}
    * 주 소 : ${address}
    * 주문시간 : ${orderTime}
    * 세금  : ${tax}원
    * 봉사료 : ${tip}원
    * 총결제금액 : ${total}원
    주문 감사합니다.
    `

    alert(bill);

    // Code Here : 폼의 모든 값을 삭제
    document.getElementById('inputForm').reset();
}

 

CSS

@charset "utf-8";

/* 문서 전체 구글 폰트 설정: Code Here  */
* {
    font-family: "Noto Sans KR", sans-serif;
    font-style: normal;
    font-optical-sizing: auto;
}

 

div 태그에 대한 css

div#container {
    width: 1000px;
    height: 100%;
    font-weight: 200;
    margin: 0 auto 20px auto;
    text-align: center;
    padding: 5px 20px;
    /* 배경색 지정 : Code Here */
    background-color: ivory;
} 

div#container > h2.title {
    margin: 20px auto;
    font-size: 2em;
    font-optical-sizing: auto;
    font-weight: 600;
    font-style: normal;
     /* 글자색 지정 : Code Here */
    color:slategrey;
}

div.banner {
    float : left;
    margin-right: 20px;
}

 

table 태그

table#inputTable td {
    padding : 5px;
}

table#inputTable tr th {
    text-align : right;
    width : 110px;
}

table#inputTable tr td {
    text-align : left;
}
table#inputTable tr input[type="text"] {
    height : 25px;
    padding:5px;
}

 

input 태그

input#address {
    width : 350px;
}
input.menuqty {
    width : 80px;
}

 

#tax, #tip, #total, .menuqty {
    text-align : right;
}

#tip, .menuqty {
    margin-right : 5px;
}

 

span.foodmenu {
    display : inline-block;
    width : 250px;
    height: 50px;
}

 

input 버튼 태그

div#btns{
    margin : 20px;
}

div#btns *{
    height: 45px;
    width: 150px;
    text-align : center;
    border: none;
    margin: 0 10px;
    color : rgb(50, 50, 255);
    /* 버튼 테두리 둥글게: Code here */
    border-radius: 20px;
}

/* 버튼에 마우스를 올렸을 때 이벤트 처리(글자 두껍게, 테두리 그림자 생성): Code here */

div#btns input:hover{
    font-weight: 900;
    box-shadow: 3px 3px 3px grey;
}

 

HTML 문서(전체)

더보기
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>야식배달</title>
    <!-- 폰트 설정 -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100..900&display=swap" rel="stylesheet">

    <link rel="stylesheet" href="./style/project.css">
    <script defer src="./script/project.js"></script>
</head>

<body>
    <div id="container">
        <h2 class="title">[ 맛있어요 야식배달! ]</h2>
        <div class="content">
            <div class="banner">
                <!-- 
                    임의의 이미지(가로 450px, 세로 350px) 를 다운받아 아래 그림이 들어가야 하는 위치에 넣으시오.
                    이미지의 크기는 그림판 등으로 크기를 조정한다.
                -->
                <img id="img" src="./images/pic.jpeg" alt="야식 1위" width="450px">
            </div>
            <div class="delivery">
                <form id="inputForm"> <!-- 메소드가 없는 경우에는 GRTMAPPING -->
                    <table id="inputTable">
                        <tr>
                            <th>현재 시간 : </th>
                            <td><input type="text" id="currTime" readonly></td>
                        </tr>
                        <tr>
                            <th>주문자 이름 : </th>
                            <td><input type="text" id="name"></td>
                        </tr>
                        <tr>
                            <th>전화번호 : </th>
                            <td><input type="text" id="phone" placeholder="예) 01011112222"></td>
                        </tr>
                        <tr>
                            <th>주 소 :</th>
                            <td><input type="text" id="address"></td>
                        </tr>
                        <tr>
                            <th>야식 메뉴 : </th>
                            <td>
                                <span class="foodmenu">
                                    <input type="checkbox" class="deli" value="7000" name="food" disabled> 떡볶이(1인분
                                    7,000원)
                                </span>
                                <input type="text" class="menuqty" id="deli" placeholder="0">인분<br>

                                <span class="foodmenu">
                                    <input type="checkbox" class="dongas" value="12000" name="food" disabled> 돈까스(1인분
                                    12,000원)
                                </span>
                                <input type="text" class="menuqty" id="dongas" placeholder="0">인분<br>

                                <span class="foodmenu">
                                    <input type="checkbox" class="pasta" value="15000" name="food" disabled> 파스타 (1인분
                                    15,000원)
                                </span>
                                <input type="text" class="menuqty" id="pasta" placeholder="0">인분<br>

                                <span class="foodmenu">
                                    <input type="checkbox" class="steak" value="22000" name="food" disabled> 스테이크 (1인분
                                    22,000원)
                                </span>
                                <input type="text" class="menuqty" id="steak" placeholder="0">인분 <br>
                            </td>
                        </tr>
                        <tr>
                            <th>세 금 : </th>
                            <td><input type="text" id="tax" value="0" disabled>원</td>
                        </tr>
                        <tr>
                            <th>봉사료 : </th>
                            <td><input type="text" id="tip" value="0" disabled>원</td>
                        </tr>
                        <tr>
                            <th>총합계 : </th>
                            <td><input type="text" id="total" value="0" disabled>원</td>
                        </tr>

                    </table>
            </div>
            <div id="btns">
                <input type="button" id="order" value="주문하기">
                <input type="reset" id="cancel" value="주문취소">
            </div>
            </form>
        </div>
    </div>
</body>

</html>