Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const tipAmount = document.querySelector(".tip-amount");
const totalAmount = document.querySelector(".total-amount");
const inputBill = document.querySelector(".bill");
const selectBtn = document.querySelectorAll("button");
Copy link
Member

Choose a reason for hiding this comment

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

배열이거나 컬렉션인 경우 변수명에 복수형을 의미하는 s를 붙여주면 좋을것 같습니다.

Suggested change
const selectBtn = document.querySelectorAll("button");
const selectBtns = document.querySelectorAll("button");

const peopleNum = document.querySelector(".number");
const resetBtn = document.querySelector(".reset-btn");
const ifZero = document.querySelector(".if-zero");
const customTip = document.querySelector(".custom");
let selectTip;

inputBill.addEventListener("click", () => {
inputBill.style.outlineColor = "hsl(185, 41%, 84%)";
});

peopleNum.addEventListener("click", () => {
peopleNum.style.outlineColor = "hsl(185, 41%, 84%)";
});

function resetBtnColor() {
for (let i = 0; i < Object.keys(selectBtn).length; i++) {
selectBtn[i].classList.remove("clicked");
}
Comment on lines +20 to +22
Copy link
Member

Choose a reason for hiding this comment

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

Javascript에서 제공하는 api를 사용해봐도 좋을 것 같습니다!

Suggested change
for (let i = 0; i < Object.keys(selectBtn).length; i++) {
selectBtn[i].classList.remove("clicked");
}
const selectBtnsKey = Object.keys(selectBtn) ;
selectBtnsKey.forEach((element) => {
// ... some logic
})

}

function inputCustom() {
if (customTip.value) {
selectTip = parseInt(customTip.value) / 100;
}
}

function clickedBtn(event) {
Copy link
Member

Choose a reason for hiding this comment

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

Button을 Click 한다는 것에서 직관적으로 받아들일 수 있어 좋은 의미인것 같습니다.
다만 clickedBtn은 변경된 button이라는 생각이 들어서 clickBtn같이 동사형을 쓰면 더욱 직관적인 코드가 될 것 같습니다.

resetBtnColor();
event.target.classList.add("clicked");
selectTip = event.target.innerText;
selectTip = parseInt(selectTip) / 100;
}

function decideZero() {
if (peopleNum.value === "0") {
ifZero.innerText = "Can't be zero";
ifZero.classList.add("not-zero");
peopleNum.style.outlineColor = "red";
} else {
ifZero.innerText = "";
ifZero.classList.remove("not-zero");
peopleNum.style.outlineColor = "hsl(185, 41%, 84%)";
}
}

function showResult() {
decideZero();
Copy link
Member

Choose a reason for hiding this comment

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

showResult()가 결과를 보여주는 부분인 것은 알기쉬워 좋았습니다.
다만 0으로 나누는 경우 거치지 않고 출력하게 되었습니다.
0으로 나누는 부분을 검사하여 decideZero()를 출력하고, return을 하면 더욱 깔끔한 코드가 될 것 같습니다.

tipCalc = (Number(inputBill.value) * selectTip) / peopleNum.value;
totalCalc = Number(inputBill.value) / peopleNum.value + tipCalc;
tipAmount.innerText = `$${tipCalc.toFixed(2)}`;
totalAmount.innerText = `$${totalCalc.toFixed(2)}`;
}

function reset() {
inputBill.value = null;
peopleNum.value = null;
tipAmount.innerText = "$0.00";
totalAmount.innerText = "$0.00";
}

for (let i = 0; i < selectBtn.length; i++) {
selectBtn[i].addEventListener("click", (e) => clickedBtn(e));
}
Comment on lines +65 to +67
Copy link
Member

Choose a reason for hiding this comment

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

for로 순회하면서 selectBtn에 함수를 넣는 것이 좋았습니다.
다만, Array.prototpy을 이용하면 더 깔끔한 코드가 될 수 있습니다.
또한 addEventListener의 경우에는 this 바인딩이 가능하여 함수를 집어 넣어도 됩니다.

selectBtn.forEach((button) => {
    button.addEventLisnter("click, clickedBtn);
}


customTip.addEventListener("keyup", inputCustom);
peopleNum.addEventListener("keyup", showResult);
Copy link

Choose a reason for hiding this comment

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

input이 여러 개 있으면 사람들은 대부분 위에서 아래로 입력하는 경향이 있지만, 아닌 경우를 고려해 어느 input이든 showResult가 이벤트 리스너로 있으면 좋을 것 같아요

window.addEventListener("load", reset);
resetBtn.addEventListener("click", reset);
98 changes: 56 additions & 42 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,44 +1,58 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- displays site properly based on user's device -->

<link rel="icon" type="image/png" sizes="32x32" href="./images/favicon-32x32.png">

<title>Frontend Mentor | Tip calculator app</title>

<!-- Feel free to remove these styles or customise in your own stylesheet 👍 -->
<style>
.attribution { font-size: 11px; text-align: center; }
.attribution a { color: hsl(228, 45%, 44%); }
</style>
</head>
<body>

Bill

Select Tip %
5%
10%
15%
25%
50%
Custom

Number of People

Tip Amount
/ person

Total
/ person

Reset

<div class="attribution">
Challenge by <a href="https://www.frontendmentor.io?ref=challenge" target="_blank">Frontend Mentor</a>.
Coded by <a href="#">Your Name Here</a>.
</div>
</body>
</html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="icon"
type="image/png"
sizes="32x32"
href="./images/favicon-32x32.png"
/>
<link rel="stylesheet" href="style.css" />
<title>Frontend Mentor | Tip calculator app</title>
</head>
<body>
<div class="top-content">SPLI</div>
Copy link

Choose a reason for hiding this comment

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

svg 파일을 사용하지 않고 로고를 직접 입력한 이유가 궁금합니다!

Copy link
Author

Choose a reason for hiding this comment

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

아 어쩐지..저것도 svg 파일이 있는 줄 몰랐어요..ㅎㅎ

<div class="top-content">TTER</div>
<div class="container">
<div class="input-content">
Bill
<input class="bill" />
Select Tip %
<div class="select-btn">
<button>5%</button>
<button>10%</button>
<button>15%</button>
<button>25%</button>
<button>50%</button>
<input class="custom" placeholder="Custom" />
</div>
<div class="info-input">
Number of People <span class="if-zero"></span>
</div>

<input class="number" />
</div>

<div class="result-content">
<div class="tip">
<div class="tip-title">
Tip Amount
<div class="tip-content">/ person</div>
</div>
<div class="tip-amount"></div>
</div>
<div class="total">
<div class="total-title">
Total
<div class="total-content">/ person</div>
</div>
<div class="total-amount"></div>
</div>
<div class="reset"><button class="reset-btn">RESET</button></div>
</div>
</div>
</body>
<script src="app.js"></script>
</html>
200 changes: 200 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
@import url("https://fonts.googleapis.com/css2?family=Kumbh+Sans&family=Nanum+Gothic&display=swap");

body {
background-color: hsl(185, 41%, 84%);
display: flex;
align-items: center;
flex-direction: column;
font-family: "Nanum Gothic", sans-serif;
font-weight: 700;
color: hsl(186, 14%, 43%);
}

.top-content {
letter-spacing: 8px;
}

.top-content:nth-child(1) {
margin-top: 5%;
}

.container {
margin-top: 5%;
display: flex;
background-color: white;
border-radius: 20px;
}

.input-content {
margin-left: 30px;
display: flex;
flex-direction: column;
justify-content: center;
}

.bill,
.number {
margin: 10px 0 20px 0;
border: none;
background-color: hsl(189, 41%, 97%);
color: hsl(184, 14%, 56%);
height: 35px;
text-align: right;
background-repeat: no-repeat;
background-position: 15px center;
font-size: 24px;
cursor: pointer;
}
Comment on lines +35 to +47
Copy link
Member

Choose a reason for hiding this comment

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

오!! 이렇게 하니깐 훨신 CSS가 깔끔해지네요!


.bill {
background-image: url(./images/icon-dollar.svg);
}

.number {
background-image: url(./images/icon-person.svg);
}

input:hover {
border: hsl(185, 41%, 84%);
}

button:hover,
.clicked {
background-color: hsl(185, 41%, 84%);
color: hsl(183, 100%, 15%);
}

.select-btn {
display: grid;
grid-template-columns: repeat(3, 1fr);
Copy link

Choose a reason for hiding this comment

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

grid에서 repeat()을 사용할 수 있는 건 이번에 처음 알았어요!

}

button {
border: none;
border-radius: 5px;
height: 35px;
background-color: hsl(183, 100%, 15%);
color: hsl(189, 41%, 97%);
font-size: 24px;
cursor: pointer;
}

.custom {
border: none;
border-radius: 5px;
background-color: hsl(189, 41%, 97%);
color: hsl(183, 100%, 15%);
text-indent: -5%;
Copy link

Choose a reason for hiding this comment

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

text-indent까지... 꼼꼼한 디자인 반영이네요

text-align: right;
font-size: 20px;
cursor: pointer;
}

.info-input {
display: inline;
}

.not-zero {
float: right;
color: red;
}

.result-content {
margin: 30px;
background-color: hsl(183, 100%, 15%);
color: white;
border-radius: 20px;
display: flex;
justify-content: center;
flex-direction: column;
}

.tip,
.total {
margin: 20px 27px;
display: inline;
flex-direction: row;
}

.tip-title,
.total-title {
float: left;
}

.total {
margin-bottom: 121px;
}

.tip-content,
.total-content {
letter-spacing: 1px;
color: hsl(185, 41%, 84%);
font-size: 10px;
}

.tip-amount,
.total-amount {
font-size: 30px;
color: hsl(185, 41%, 84%);
float: right;
}

.reset {
display: flex;
justify-content: center;
align-items: center;
}

.reset-btn {
color: hsl(183, 100%, 15%);
background-color: hsl(186, 14%, 43%);
width: 300px;
}

@media only screen and (max-width: 375px) {
.container {
display: flex;
flex-direction: column;
width: 374px;
padding: 20px;
}
.result-content {
width: 350px;
height: 270px;
display: flex;
justify-content: center;
}
.total {
margin-bottom: 80px;
}
.select-btn {
display: grid;
grid-template-columns: repeat(2, 1fr);
justify-content: center;
}
.select-btn button,
.custom {
width: 120px;
margin: 10px;
}
}
@media only screen and (min-width: 375px) {
.container {
width: fit-content;
}
.select-btn button,
.custom {
width: 80px;
}
.result-content {
width: 400px;
height: 340px;
}
.select-btn button:nth-child(-n + 3) {
margin: 12px 0;
}
.select-btn button:nth-child(n + 4),
.select-btn input {
margin-bottom: 20px;
}
}
3 changes: 3 additions & 0 deletions todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- View the optimal layout for the app depending on their device's screen size
- See hover states for all interactive elements on the page
- Calculate the correct tip and total cost of the bill per person