사전 캠프/추가 과제

스타벅스 주문 시스템 만들기 (난이도 상) (완료)

Iruka913 2024. 9. 19. 17:50

index.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="stylesheet" href="styles.css">
</head>

<body>
    <h1>스타벅스 메뉴</h1>

    <div id="menu">
        <h2>메뉴</h2>
        <!-- 메뉴 아이템이 여기에 추가될 것입니다 -->
    </div>

    <div id="order-summary">
        <h2>주문 내역</h2>
        <ul id="order-list"></ul>
        <p>총 가격: ₩<span id="total-price">0</span></p>
        <button id="submit-order">주문 제출</button>
    </div>
    <script src="script.js"></script>
</body>

</html>

 

script.js

document.addEventListener('DOMContentLoaded', () => {
    const menu = [
        { name: '아메리카노', price: 4100 },
        { name: '카페라떼', price: 4600 },
        { name: '카푸치노', price: 4600 },
        { name: '카라멜 마끼아또', price: 5800 },
        { name: '자바 칩 프라푸치노', price: 6300 },
        { name: '딸기 요거트 블렌디드', price: 6300 }
    ];

    let order = {}; // 주문 항목을 저장하는 딕셔너리.
    let totalPrice = 0; // 전체 값.

    const menuContainer = document.getElementById('menu');
    const orderList = document.getElementById('order-list');
    const totalPriceElement = document.getElementById('total-price');
    const submitOrderButton = document.getElementById('submit-order');

    menu.forEach((item, index) => {

        let divall = document.createElement('div'); // 커피 이름과 가격, 주문 추가 버튼이 다 들어있는 올인원 영역
        divall.classList.add('linebox'); // 올인원 영역 클래스는 linebox

        let div1 = document.createElement('div');
        div1.classList.add('cofname');
        let span1 = document.createElement('span');
        span1.textContent = `${item.name}`;

        div1.appendChild(span1)

        let div2 = document.createElement('div') // 커피 가격과 주문 추가 버튼이 들어있는 영역.
        div2.classList.add('price-btn'); // 해당 영역 클래스는 price-btn
        let span2 = document.createElement('span');
        span2.id = 'cofprice';
        span2.textContent = `₩${item.price}`;
        let button = document.createElement('button');
        button.id = 'addbtn';
        button.innerText = '주문 추가.';
        button.setAttribute('data-index', index); // 각 메뉴 아이템의 인덱스를 저장

        div2.appendChild(span2)
        div2.appendChild(button)

        divall.appendChild(div1)
        divall.appendChild(div2) // 합체.

        document.getElementById('menu').appendChild(divall) // 오더 리스트에 추가.

    });

    menuContainer.addEventListener('click', (event) => {
            // 버튼이 눌릴 시에 발동.
        if (event.target.tagName === 'BUTTON') {
            // 어떤 메뉴의 버튼이 눌릴 시.
            const index = event.target.getAttribute('data-index');
            // 클릭된 버튼의 data-index 속성을 가져옴
            const selectedItem = menu[index];
            // 메뉴 배열에서 해당 메뉴를 찾아옴 ex)아메리카노가 선택되면 0번째로 지정되겠지?

            if (!order[selectedItem.name]) {  
                order[selectedItem.name] = {
                    price: selectedItem.price,
                    quantity: 1
                }; // order 리스트에 선택된 아이템의 이름이 존재하지 않을 시
                   // price의 밸류를 선택된 커피의 값으로 변경.
                   // quantity 키 생성 및 밸류를 1로 설정.
                   // ex)아메리카노가 선택될 시, 0번째 인덱스의 이름을 조회.
                   // 아메리카노의 수량을 1로 설정.
            } else {
                order[selectedItem.name].quantity += 1;
                   // order 리스트에 선택된 아이템의 이름이 존재할 시.
                   // quantity의 밸류를 1 늘린다.
                   // 아메리카노가 이미 장바구니에 들어있으면, 아메리카노의 수량이 1에서 2가 된다.
            }

            totalPrice += selectedItem.price;
            // 총합 가격은 selectedItem이란 딕셔너리의 price.
            updateOrderList();
            //주문 내역 업데이트 함수 불러오기.
        }
    });

    // 주문 내역 업데이트 함수
    function updateOrderList() {
        orderList.innerHTML = '';
        for (let itemName in order) {
            const orderItem = order[itemName];
            const orderItemElement = document.createElement('li');
            orderItemElement.classList.add('orderitemelements');
            orderItemElement.innerHTML = `
                ${itemName} - ₩${orderItem.price.toLocaleString()} x${orderItem.quantity}
                <button class="remove" data-item="${itemName}">삭제</button>
            `;
            orderList.appendChild(orderItemElement);
        }
        totalPriceElement.textContent = totalPrice.toLocaleString();
    }

    // 아이템 삭제 로직
    orderList.addEventListener('click', (event) => {
        const itemName = event.target.getAttribute('data-item');
        if (event.target.classList.contains('remove')) {
            totalPrice -= order[itemName].price * order[itemName].quantity;
            delete order[itemName];
            updateOrderList();
        }
    });

    // 주문 제출 로직
    submitOrderButton.addEventListener('click', () => {
        if (Object.keys(order).length > 0) {
            alert('주문해 주셔서 감사합니다!');
            order = {};
            totalPrice = 0;
            updateOrderList();
        } else {
            alert('주문 내역이 비어 있습니다!');
        }
    });
});

 

styles.css

body {
    font-family: Arial, sans-serif;
    padding: 20px;
    max-width: 600px;
    margin: 0 auto;
}

h1 {
    text-align: center;
}

h2 {
    margin-left: 10px;
}

p {
    margin-left: 10px;
}

#menu {
    border: solid 1.5px gray;
    border-radius: 5px;

}

#order-summary {
    border: solid 1.5px gray;
    border-radius: 5px;
    margin-top: 10px;
}

/* 여기에 #menu와 #order-summary의 스타일을 추가하세요. */
/* 버튼과 관련된 스타일은 아래의 예시를 참고하여 완성하세요. */

button {
    background-color: #00704a;
    color: white;
    padding: 10px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

button:hover {
    background-color: #005936;
}

#submit-order {
    display: block;
    /* block 요소로 변경 */
    margin: 20px auto;
    /* 중앙 정렬 */
    width: 90%;
    /* 부모의 80% 너비를 차지 */
    background-color: #00704a;
    color: white;
    /* 버튼을 크게 보이게 하기 위한 패딩 */
    border: none;
    border-radius: 5px;
    /* 글씨 크기 조정 */
    cursor: pointer;
}

.orderitemelements {
    margin-top: 5px;
}

.remove {
    background-color: red;
    color: white;
    padding: 10px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

.remove:hover {
    background-color: pink
}

.linebox {
    display: flex;
    justify-content: space-between;
    /* 라인박스를 조정해서 양 옆에 공간을 두고 요소들이 배치되게끔 조정함.  */
    height: 50px;
    /* 키를 조정해서 요소 간 간격이 어느 정도 있게 유격을 생성. */
}

.cofname {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    margin-left: 10px;
}

.price-btn {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
}

#cofprice {
    margin-right: 10px;
}

#addbtn{
    margin-right: 10px;
}