Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ 2주차 기본/심화(to be continue..) ] 가계부 💸 #5

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
94 changes: 94 additions & 0 deletions assignment/week02/assign2/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css"/>
<title>가계부</title>
</head>
<body>
<header>유진이의 가계부</header>
<section id="total">
<header>나의 자산</header>
<strong id="totalMoney">249700</strong>
<div id="plusminus">
<div><span class="sign">+</span><span id="income_tot">300000</span></div>
<div><span class="sign">-</span><span id="outcome_tot">300000</span></div>
</div>
</section>

<section id="detail">
<div id="date">
<img src="../../week01/assign4/img/left.png" alt="leftbtn"/>
<header>10월 1일</header>
<img src="../../week01/assign4/img/right.png" alt="rightbtn"/>
</div>

<div id="datebelow">
<div>내역 리스트</div>
<div>
<input checked type="checkbox" id="in"/>
<label for="in">수입</label>
<input checked type="checkbox" id="out"/>
<label for="out">지출</label>
</div>
</div>
<section class="deleteModalWrap">
<div class="deleteModalBody">
<div>정말로 삭제하겠습니까?</div>
<div id="modal-in-out">
<input type="radio" id="closeYes" name="closeYes"/>
<label for="closeYes">예</label>
<input type="radio" id="closeNo" name="closeNo"/>
<label for="closeNo">취소</label>
</div>
</div>
</section>
</section>
<section id="detaillist">
</section>
<section id="bottom">
<div>+</div>
</section>
<section class="modalWrap">
<div class="modalBody">
Comment on lines +48 to +54

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적으로 class명, id명을 혼합해서 사용하는것 같아요!
css 스타일링 할 때, js로 요소를 가져올 때 일정한 규칙 없이 클래스, id를 사용하면 개발 할 때도 어렵고 유지보수 및 가독성 측면에서도 단점이 될 수 있습니댜!
이전에 알려주었던 bem 방식 등을 참고해서,
id, class 중 어떤 것을 사용해야 할지 / 클래스명이나 id 명을 짓는 일정한 규칙 등에 대해 더 고민해보면 좋을것 같아!!

<h1>내역 추가</h1>
<section id="modal-in-out">
<input checked type="radio" id="add-in" name="inout"/>
<label for="add-in">수입</label>
<input type="radio" id="add-out" name="inout"/>
<label for="add-out">지출</label>
</section>
<section id="modal-category">
<header>종류</header>
<div id="add-category-in">
<select id="category-in">
<option value="과외" name="category-in">과외</option>
<option value="용돈" name="category-in">용돈</option>
</select>
</div>
<div id="add-category-out">
<select id="category-out">
<option value="식비" name="category-out">식비</option>
<option value="쇼핑" name="category-out">쇼핑</option>
</select>
</div>

</section>
<section id="modal-amount">
<header>금액</header>
<input id="input-amount" />
</section>
<section id="modal-content">
<header>내용</header>
<input type="text" id="input-content"/>
</section>
<section id="modal-btn">
<button type="button" class="modal-saveBtn">저장하기</button>
<button type="button" class="modal-closeBtn">닫기</button>
</section>
</div>
</section>
<script src="index.js"></script>
</body>
</html>
207 changes: 207 additions & 0 deletions assignment/week02/assign2/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
let history_list=[
{
category:"과외비",
detail:"10월 월급",
amount: 500000
},{
category:"식비",
detail:"서브웨이",
amount:-30000
},{
category:"용돈",
detail:"10월 용돈",
amount:100000
},{
category:"식비",
detail:"수육국밥",
amount:-10000
}];
Comment on lines +1 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

컨벤션을 어떻게 정하냐에 따라 달라지겠지만,
보통 상수값은 대문자로 표시해줘서 이 값은 상수값이다!라는 점을 한 눈에 알아볼수 있게 해주는 것이 좋아요!

Suggested change
let history_list=[
{
category:"과외비",
detail:"10월 월급",
amount: 500000
},{
category:"식비",
detail:"서브웨이",
amount:-30000
},{
category:"용돈",
detail:"10월 용돈",
amount:100000
},{
category:"식비",
detail:"수육국밥",
amount:-10000
}];
let HISTORY_LIST=[
{
category:"과외비",
detail:"10월 월급",
amount: 500000
},{
category:"식비",
detail:"서브웨이",
amount:-30000
},{
category:"용돈",
detail:"10월 용돈",
amount:100000
},{
category:"식비",
detail:"수육국밥",
amount:-10000
}];

let filteredList=history_list;
let clickedIncome=true, clickedOutcome=true;

const total=document.querySelector("#totalMoney");
let detaillist=document.querySelector("#detaillist");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detaillist는 변경되지 않는 요소인것 같은데..!
const가 아닌 let으로 선언한 이유가 있을까용? 궁금합니다!!

const income=document.querySelector("#income_tot");
const outcome=document.querySelector("#outcome_tot");
const inBtn=document.querySelector("#in");
const outBtn=document.querySelector("#out");
const addBtn=document.querySelector("#bottom div");
const modal = document.querySelector('.modalWrap');
var radio = document.getElementsByName("inout");
const c_in = document.getElementById('category-in');
const c_out= document.getElementById('category-out');
const m_input=document.querySelector('#input-amount');
const m_content=document.querySelector('#input-content');

const submitBtn=document.querySelector('.modal-saveBtn');
const closeBtn = document.querySelector('.modal-closeBtn');
const closeModal = document.querySelector('.deleteModalWrap');
let inputAmount=0;
let inputContent="";
let inputSign=1;
let inputCategory="";

makeHistoryList();
calculateHistory();

inBtn.addEventListener("click",infilter);
outBtn.addEventListener("click",outfilter);
addBtn.addEventListener("click",addList);
submitBtn.addEventListener("click",submitList);
Comment on lines +47 to +50

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이벤트리스너 부분도 같은 기능 수행하는것끼리 묶어서 함수로 캡슐화 해보는건 어떨까용 ?!


c_in.addEventListener("change",function(event){
inputCategory=event.target.value;
})
c_out.addEventListener("change",function(event){
inputCategory=event.target.value;
})
m_input.addEventListener("input",function(event){
if(isNaN(event.target.value)){
window.alert("숫자 외의 문자는 입력할 수 없습니다.");
// 숫자아닌건 없애도록 replace하는 정규식
event.target.value=event.target.value.replace(/[^0-9]/g,"");
}else{
inputAmount=event.target.value;
}
})
m_content.addEventListener("change",function(event){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전역에 두지말고 함수로 묶으면 더 좋을거같오..!!

inputContent=event.target.value;
})


function infilter(){
clickedIncome=(!clickedIncome);
doFilter()
}

function outfilter(){
clickedOutcome=(!clickedOutcome);
doFilter()
}

function doFilter(){
detaillist.replaceChildren();
if(clickedIncome && clickedOutcome)
filteredList=history_list;
else if(clickedIncome)
filteredList=history_list.filter((each)=>each.amount>0);
else if(clickedOutcome)
filteredList=history_list.filter((each)=>each.amount<0);
else
filteredList=[];

makeHistoryList();
}
Comment on lines +82 to +94

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

필터링 구현이 어려웠다고 해서 코멘트 남깁니댱 !!

나눈 필터링을 체크박스 선택 값(input checkbox 가져와서, .checked로 확인)에 따라서, display : flex & display : none 속성을 적용하도록 해서 구현했었어!
지금처럼 필터링 한 리스트를 만들어서 html에 반영해줘도 좋지만,
필터링을 한다고 해서 삭제되거나 새로 추가되는 것은 아니니까 css의 display 속성을 활용해서 구현해주면 더 로직이 간단해질수 있을것 같아!

정답은 없으니깡 내가 구현한 방법이랑 비교해서 고민해보면 좋을것 같아용 ㅎㅎ


function makeHistoryList(){
filteredList.forEach((each)=>{

const eachlist = document.createElement('div');
const category = document.createElement('div');
const detail = document.createElement('div');
const amount = document.createElement('div');
const xbtn = document.createElement('div');
Comment on lines +99 to +103

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

js로 element를 create 할 때도! div보다 section, article, button 등의 시맨틱 태그들을 사용해주면 더 좋을것 같아용


category.innerText=each.category;
detail.innerText=each.detail;
amount.innerText=each.amount;
xbtn.innerText='x';

eachlist.appendChild(category);
eachlist.appendChild(detail);
eachlist.appendChild(amount);
eachlist.appendChild(xbtn);

eachlist.classList.add('eachlist');
detaillist.appendChild(eachlist);

each.amount<0 ? amount.classList.add('out') : amount.classList.add('in')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

삼항연산자 너무 적절히 잘 썼다 !!!🔥


xbtn.classList.add('xbtn');
xbtn.addEventListener('click', deleteHistory);


})
}

function deleteHistory(event){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

내가 삭제 모달 구현할 때 [fillter로 삭제][함수 모달띄우기]로 나눠서 구현하니까 이벤트리스너가 중복되어서 이전에 아니요 눌렀던 애들까지 다 삭제되는 이슈가 있어서.. 포기하고 코드리뷰 하러 왔는데
언니처럼 함수를 나누지 않고 한 함수안에서 구현하니까 이벤트리스너가 중복되지 않는구나!! 함수를 나누는 과정에서 뭔가 문제라는걸 알아냈어...뭐가 문제인진 더 생각해봐야겠당

closeModal.style.display="block";
let yes = document.querySelector('#closeYes');
let no = document.querySelector('#closeNo');

yes.addEventListener("click",(e)=>{
if(e.target.value){
detaillist.removeChild(event.target.parentNode);
const idx= history_list.findIndex(each => each.detail ===event.target.previousElementSibling.previousElementSibling.innerText)
history_list.splice(idx,1);
closeModal.style.display="none";
doFilter()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

나도 삭제하거나 추가할 때 계산하고 fillter해서 보여주는 함수 계속 중복해서 썼어!

calculateHistory();
}
})
Comment on lines +137 to +141

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리스트 삭제 시 필터링 함수가 실행되어야 하는 이유에 대해 궁금합니다!!
doFilter()를 여기서 실행하지 않으면 결과 값이 어떻게 되나요 ?!


no.addEventListener("click",(e)=>{
e.target.value && (closeModal.style.display="none")
})

}

function calculateHistory(){
let init_balance=0;
let income_total=0;
let outcome_total=0;
Comment on lines +150 to +152

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기도 magic number, 수치값 등을 나타내는 상수는 대문자로 바꿔주면 더 좋을것 같습니당!

Suggested change
let init_balance=0;
let income_total=0;
let outcome_total=0;
let INIT_BALANCE=0;
let INCOME_TOTAL=0;
let OUTCOME_TOTAL=0;

이런식으로 나타내면 단순 변수인지, 상수화해서 나타낸 값인지 한 눈에 비교하기 쉽습니댱

history_list.forEach((each)=>{
init_balance+=each.amount;
each.amount<0 ? outcome_total+=each.amount : income_total+=each.amount;
})
total.innerText=init_balance;
income.innerText=income_total;
outcome.innerText=outcome_total;
}

function addList(){
modal.style.display = 'block';
}

function submitList(){
if(inputCategory=="" || inputAmount==""|| inputContent==""){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위에서 전역으로 eventlistener 선언했을 때 하나는 event가 발생하고 다른건 안발생하면 어떻게 되는거지? 하고 궁금했는데 여기서 처리를 해주는건가???

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

논리연산자로 조건문 구현한거 넘 완벽해..👍

window.alert("아직 입력되지 않은 항목이 있습니다.");
console.log('null');
}else{
history_list.push({
category:inputCategory,
detail:inputContent,
amount: inputAmount*inputSign
})
window.alert("저장되었습니다.");
detaillist.replaceChildren();
makeHistoryList();
calculateHistory();
}


}

closeBtn.onclick = function() {
modal.style.display = 'none';
}

for(var i=0 ; i < radio.length ; i++){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 i를 var로 선언한 이유가 궁금합니당 !!

radio[i].addEventListener('click', function () {
if(this.id === "add-in"){
console.log("in");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

console.log는 꼬옥 지워주기 !!

inputSign=1;
inputCategory=c_in.options[c_in.selectedIndex].value;
document.getElementById('add-category-in').style.display="block";
document.getElementById('add-category-out').style.display="none";
}else{
console.log("out");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요기도 ~

inputSign=-1;
inputCategory=c_out.options[c_out.selectedIndex].value;

document.getElementById('add-category-out').style.display="block";
document.getElementById('add-category-in').style.display="none";
}
console.log(inputCategory);
})
}
Loading