안녕하세요 TriplexLab 입니다. 오늘은 moonbucks-menu 스탭1을 이어서 스탭2 회고를 작성해보겠습니다.
moonbucks-menu 스탭1 회고 참고해주세요. 👍👍
👉 스탭 2 중간즘 에서 얻은 인사이트
1. 상태값이 중요한 이유는 사용자에게 입력 받은 정보(상태)를 저장하고, 불러와줘야 동적인 웹페이지를 만들수가 있습니다. - (EX) 채팅창으로 예시로 들면 A라는 채팅방,B라는 채팅방,C라는 채팅방들을 각각 동립적인 채팅방을 만들기 위해서는 상태값이 중요합니다.(여기서 각각 채팅방을 인스턴스로 동적으로 생성할수 있습)
// Step2
// TODO localStorage Read & Write
// - [x] localStorage에 데이터를 저장한다.
// - [x] 메뉴를 추가할 때
// - [x] 메뉴를 수정할 때
// - [x] 메뉴를 삭제할 때
// - [x] localStorage에 있는 데이터를 읽어온다.
// TODO 카테고리별 메뉴판 관리
// - [x] 에스프레소 메뉴판 관리
// - [x] 프라푸치노 메뉴판 관리
// - [x] 블렌디드 메뉴판 관리
// - [x] 티바나 메뉴판 관리
// - [x] 디저트 메뉴판 관리
// TODO 페이지 접근시 최초 데이터 Read & Rendering
// - [x] 최초로 로딩될때 localStorage에 에스프레소 메뉴를 읽어온다.
// - [x] 에스프레소 메뉴를 페이지에 그려준다.
// TODO 품절 상태 관리
// - [] 품절 상태인 경우를 보여줄 수 있게, 품절 버튼을 추가하고 sold-out class를 추가하여 상태를 변경한다.
// - [] 품절 버튼을 추가한다.
// - [] 품절 버튼을 클릭하면 localStorage에 상태값이 저장된다.
// - [] 클릭이벤트에서 가장가까운 li태그에 class속성 값이 sold-out을 추가한다.
const $ = element => document.querySelector(element);
const store = {
setLocalStorage(menu) {
localStorage.setItem("menu", JSON.stringify(menu));
},
getLocalStorage() {
return JSON.parse(localStorage.getItem("menu"));
}
}
function App(){
// 상태를 변하는 데이터, 이 앱에서 변하는 것이 무엇인가 - 메뉴명
this.menu = {
espresso: new Array(),
frappuccino: new Array(),
blended: new Array(),
teavana: new Array(),
desert: new Array()
};
this.currentCategory = 'espresso';
const render = () => {
const template = this.menu[this.currentCategory].map((menuItem, idx) => {
return `<li data-menu-id="${idx}" class="menu-list-item d-flex items-center py-2">
<span class="w-100 pl-2 menu-name">${menuItem.name}</span>
<button type="button" class="bg-gray-50 text-gray-500 text-sm mr-1 menu-edit-button">
수정
</button>
<button type="button" class="bg-gray-50 text-gray-500 text-sm menu-remove-button">
삭제
</button>
</li>`
}).join(''); //배열객체에 있는 li항목 들을 하나로 합쳐주는 join역할
$('#menu-list').innerHTML = template
updateMenuCount();
};
const updateMenuCount = () => {
const mentCount = $('#menu-list').querySelectorAll('li').length;
$('.menu-count').innerText = `총 ${mentCount}개`;
};
const addMenuName = () => {
if($('#menu-name').value === ''){
alert('값을 입력해주세요.');
return;
}
const menuName = $('#menu-name').value;
this.menu[this.currentCategory].push({ name: menuName });
store.setLocalStorage(this.menu); //상태가 변하는 시졈에 localStorage에 데이터를 저장한다.
render();
$('#menu-name').value = '';
};
const updateMenuName = (e) => {
const menuId = e.target.closest('li').dataset.menuId;
const $menuName = e.target.closest('li').querySelector('.menu-name');
const updateedMenuName = prompt('메뉴명을 수정하세요', $menuName.innerText);
this.menu[this.currentCategory][menuId].name = updateedMenuName; //기존에 있던 this.menu 배열에 수정하여 저장한다.
store.setLocalStorage(this.menu); //그리고 다시 localStorage에 데어터를 저장한다.
$menuName.innerText = updateedMenuName;
};
const removeMenuName = (e) => {
if(confirm('정말 삭제하시겠습니까?')){
const menuId = e.target.closest('li').dataset.menuId;
this.menu[this.currentCategory].splice(menuId, 1);
store.setLocalStorage(this.menu);
e.target.closest('li').remove();
updateMenuCount();
}
}
$("#menu-list").addEventListener("click", (e) => {
if(e.target.classList.contains('menu-edit-button')) {
updateMenuName(e);
}
if(e.target.classList.contains('menu-remove-button')){
removeMenuName(e);
}
});
$('#menu-form').addEventListener('submit', (e) => {
e.preventDefault();
});
$('#menu-name').addEventListener('keypress', (e) => {
if(e.key !== 'Enter') return;
addMenuName();
});
$('#menu-submit-button').addEventListener('click', addMenuName);
$('nav').addEventListener('click', (e) => {
const isCategoryButton = e.target.classList.contains('cafe-category-name');
if(isCategoryButton){
const categoryName = e.target.dataset.categoryName;
this.currentCategory = categoryName;
$('#category-title').innerText = `${e.target.innerText} 메뉴 관리`;
render();
}
});
this.init = () => {
if(store.getLocalStorage()){
this.menu = store.getLocalStorage()
render();
}
};
}
const app = new App();
app.init();
여기까지 중간즘 진행한 작업 파일을 공유합니다. 아래파일을 참고하세요~ 👍👍
moonbucks-menu 스탭2 회고
👉 스탭 2에서 얻은 인사이트
1. 카테고리 메뉴 추가할때 아래처럼 this.menu를 객체를 만들어서 각각의 카테로기 별로 데이터를 관리할수 있는 형태를 사용할수 있어서 신기했다. 그리고 현재카테로기명을 초기화를 해서 사용
2. undefined은 기본적으로 Falsy한 값을 가지고 있어서 앞에 느낌표를 붙여주면 true 로전환됩니다.
this.menu = {
espresso: new Array(),
frappuccino: new Array(),
blended: new Array(),
teavana: new Array(),
desert: new Array()
};
this.currentCategory = 'espresso';
this.init = (name) => {
const message = store.getLocalStorage(name)
if(message){ //localStorage에 값이 있을때만
this.menu = message; // 값을 this.menu에 할당한다.
}
render();
};