4 분 소요

스타벅스를 복제해봅시다 ~ 🧑‍💻

Wecode의 첫번째 과제.....webucks만들기....한번해봅시다.

[Mission 1] 로그인 페이지 레이아웃 구현 #1

과제의 사진을 보고 똑같이 구현하라.

<body>
  <section class="container">
    <div class="login-logo">
      <img src="./images/logo.png" alt="로고이미지" />
    </div>
    <form class="login-form">
      <input
        id="id"
        placeholder="전화번호, 사용자 이름 또는 이메일"
        autocomplete="off"
      />
      <input type="password" id="pw" placeholder="비밀번호" />
      <button class="showHide" type="button">
        show
      </button>
      <button id="toList" type="button">
        로그인
      </button>
    </form>
    <div class="login-forget">
      <a href="#">비밀번호를 잊으셨나요?</a>
    </div>
  </section>
  <script src="./js/login.js"></script>
</body>

크게 <section> 안에 2개의 <div>와 1개의 <form>으로 만들었다.

form안에는 로그인,패스워드의 input태그와 1개의 버튼으로 이루어져있다.

form에 flex를 주어 세로정렬시키고 margin을 통해 약간씩 띄어주었다.


[Mission 2] 로그인 페이지 기능 구현 #2

1 - 아이디값으로 @가 들어오면 input창이 초록색으로
2 - 비밀번호값으로 대문자,소문자,숫자,특수기호가 포함되고 길이가 8자이상이면 input창 초록색으로
3 - 이 두개의 조건을 모두 갖추면 버튼이 활성화되게 하라.
4 - 또한 show,hide버튼을 만들어 비밀번호의 값이 보이게,안보이게 구현하라.

id.addEventListener("input", (e) => {
  const num = pw.value.search(/[0-9]/g);
  const eng = pw.value.search(/[a-z]/gi);
  const spe = pw.value.search(/[`~!@@#$%^&*|₩₩₩'₩";:₩/?]/gi);
  if (
    id.value.includes("@") &&
    pw.value.length > 7 &&
    num > -1 &&
    eng > -1 &&
    spe > -1
  ) {
    button.style.backgroundColor = "#79BAF2";
  } else {
    button.style.backgroundColor = "#b4d2e8";
    id.style.borderColor = "#dddddd";
  }
  if (id.value.includes("@")) {
    id.style.borderColor = "#659c31";
  } else {
    id.style.borderColor = "#dddddd";
  }
});

코드가 길어지니 아이디의 이벤트만 보도록한다.

정규식을 통해 비밀번호의 값을 확인하였고 if문으로 구현하였다.

serch는 원하는 값이 있으면 해당값의 인덱스를 없으면 -1을 반환하기에 위와같이 작성하였다.



[Mission 3] 커피 리스트 페이지 레이아웃 구현 #3

과제의 사진을 보고 똑같이 구현하세요.


// 콜드브루 아이템들
const 에스프레소 = [
  { name: "아이스 토피 넛 라떼" },
  { name: "토피 넛 라떼" },
  { name: "에스프레소 콘 파나" },
  { name: "에스프레소 마키아또" },
  { name: "아이스 카페 아메리카노" },
  { name: "카페 아메리카노" },
  { name: "아이스 카라멜 마키아또" },
  { name: "카라멜 마키아또" },
  { name: "아이스 카푸치노" },
  { name: "카푸치노" },
  { name: "라벤더 카페 브레베" },
  { name: "럼 샷 코르타도" },
  { name: "바닐라 빈 라떼" },
  { name: "블론드 에스프레소 라떼" },
  { name: "사케라또 비안코 오버 아이스" },
];

//페이지 렌더링되면 보여줌
window.addEventListener("load", () => {
  showItems(콜드브루, 0, "coffee");
});
//페이지 렌더링되면 보여줌
window.addEventListener("load", () => {
  showItems(에스프레소, 1, "coffeeshot");
});

//나열함수
function showItems(item, num, what) {
  for (let i = 1; i < item.length; i++) {
    const add = document.createElement("div");
    const img = document.createElement("img");
    const h4 = document.createElement("h4");
    const like = document.createElement("span");
    const name = document.createElement("div");

    like.setAttribute("class", "like");
    add.setAttribute("class", "add");
    img.setAttribute("src", `./images/${what}${i}.png`);
    img.setAttribute("alt", `${item[i].name}`);
    name.setAttribute("class", "name");
    h4.innerHTML = item[i].name;
    like.innerHTML = `&nbsp;&nbsp;&nbsp;&nbsp;🤍`;

    like.addEventListener("click", () => {
      if (like.innerHTML === `&nbsp;&nbsp;&nbsp;&nbsp;🤍`) {
        like.innerHTML = `&nbsp;&nbsp;&nbsp;&nbsp;❤️`;
      } else like.innerHTML = `&nbsp;&nbsp;&nbsp;&nbsp;🤍`;
    });

    add.appendChild(img);
    add.appendChild(name);
    name.appendChild(h4);
    name.appendChild(like);

    document.getElementsByClassName("상품들")[num].appendChild(add);
  }
}


이부분은 고민을 조금하였다.

html에 전부 써주자니 html이 너무 더러워보였다.

그래서 내가 보여줘야할 item들을 배열에 저장시키고

window의 load이벤트를 통해 페이지가 렌더링되면~

동적으로 요소들을 생성하여 그값들을 flex, space-between을 통해 나열하였다.



[Mission 4] 커피 상세 페이지 레이아웃 구현 #4

과제의 사진과 같이 만들어라.


    <div class="container">
      <h2>콜드 브루</h2>
      <div class="detail-img">
        <img src="./images/coffee11.png" alt="화이트 초콜릿 모카" />
      </div>
      <div class="detail-info">
        <h3 class="title">화이트 초콜릿 모카</h3>
        <span class="like"></span>
        <p class="smallP">White chocolate Mocha</p>
        <p class="info">
          달콤하고 부드러운 화이트 초콜릿 시럽과 에스프레소를 스팀 밀크와 섞어
          휘핑크림으로 마무리한 음료로 달콤함과 강렬한 에스프레소가 부드럽게
          어우러진 커피
        </p>
        <div class="item">
          <p class="item-info">제품 영양 정보</p>
          <span class="item-span">Tall() / 355ml (12 fl oz)</span>
        </div>
        <div class="detail-kcal">
          <div class="division">
            <div class="kcal">
              <p>1 제공량 (kcal)</p>
              <p>345</p>
            </div>
            <div class="kcal">
              <p>1 제공량 (kcal)</p>
              <p>345</p>
            </div>
            <div class="kcal">
              <p>1 제공량 (kcal)</p>
              <p>345</p>
            </div>
          </div>
          <div class="division">
            <div class="kcal2">
              <p>1 제공량 (kcal)</p>
              <p>345</p>
            </div>
            <div class="kcal2">
              <p>1 제공량 (kcal)</p>
              <p>345</p>
            </div>
            <div class="kcal2">
              <p>1 제공량 (kcal)</p>
              <p>345</p>
            </div>
          </div>
        </div>
        <div class="알러지">알레르기 유발 요인 : 우유</div>
        <div class="review">
          <h2>리뷰</h2>
          <div class="comment"></div>
          <input
            placeholder="리뷰를 입력해주세요."
            id="commentInput"
            type="text"
          />
        </div>


큰 틀로보면 <div>안에 <h2>1개와 <div>2개로 이루어져 있다.

flex를 써도 되지만 float도 써보고 싶어 옆의 <div>는 float:right를 통해 이미지와 나란히 배치시켰다.

그 밑으로는 모두 flex를 사용하여 구현하였다




[Mission 5] 커피 상세 페이지 기능 구현 #5

좋아요 버튼 구현과 댓글 추가기능 구현하라.

const likeSpan = document.getElementsByClassName("like")[0];
// 하트
likeSpan.addEventListener("click", () => {
  if (likeBool === false) {
    likeSpan.innerHTML = "❤️";
    likeBool = true;
  } else {
    likeSpan.innerHTML = "";
    likeBool = false;
  }
});

const comment = document.querySelector(".comment");
const input = document.getElementById("commentInput");
//엔터치면 댓글
input.addEventListener("keydown", (e) => {
  if (e.keyCode === 13) {
    //감싸는 박스 div
    const commentBox = document.createElement("div");
    commentBox.setAttribute("class", "commentBox");
    //텍스트 추가 span
    const commentText = document.createElement("span");
    commentText.setAttribute("class", "commentText");
    commentText.innerHTML =
      "<b>" + sessionStorage.getItem("id") + "</b>" + " : " + e.target.value;
    //좋아요 span
    const likeBtn = document.createElement("span");
    let likeNum = 0;
    likeBtn.setAttribute("class", "likeBtn");
    likeBtn.innerHTML = `  ❤️ ${likeNum}명`;
    likeBtn.addEventListener("click", () => {
      likeNum++;
      console.log(likeNum);
      likeBtn.innerHTML = ` ➡️ ❤️ ${likeNum}명`;
    });
    //삭제 button
    const deleteBtn = document.createElement("button");
    deleteBtn.setAttribute("class", "deleteBtn");
    deleteBtn.innerHTML = "삭제";
    deleteBtn.addEventListener("click", () => {
      comment.removeChild(commentBox);
    });
    //실제로 달기
    commentText.appendChild(likeBtn);
    commentBox.appendChild(commentText);
    commentBox.appendChild(deleteBtn);
    comment.appendChild(commentBox);

    input.value = "";
  }
});


리뷰 역시 동적으로 요소들을 생성하여 구현하였고

로그인할때의 아이디값을 어떻게 받아올지 구상하다가 Session storage를 통해서

값을 옮기면 되겠다고 생각하여 구글링을 통해 완성하였다.




[Mission 6] 도전 과제 #6

리뷰별로 좋아요버튼과 삭제버튼을 만들어주세요. 커피 이름 옆 좋아요 버튼(하트)를 눌렀을 때 붉은색 하트로 변하게 구현해주세요


위와 같은 코드를 통해 해결하였고 구현한 것을 사진으로 대체하겠다.

loginpage


로그인 페이지


list


리스트 페이지


detail


디테일 페이지




이번 과제를 하며 느낀점!
변수명을 잘써야겠다.....내가봐도 모르겠다;;
시작하기전에 80%정도는 구상을 끝내고 내가 구상한게 구현되는지 확인 후 시작하자(40%정도에서 시작하면 코드가 갈수록 더러워진다.)
기능구현에서 그치지말고 좀 더 세밀하게 디테일에 신경쓰자......특히 이부분이 절실하다. 절대 만족하지말자.
오늘 느꼈던것을 까먹지말자.(정신차리자)

업데이트: