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기 소인성] 로또 미션 STEP3 #112

Merged
merged 48 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
fab4ea0
feat: remove requirements
pocojang Mar 14, 2022
4c8a485
🔬Chore: 개발 환경을 설정한다.
InSeong-So Mar 16, 2022
fed0928
🎆Style: 스탭 1 기능에 대한 HTML/CSS를 수정한다.
InSeong-So Mar 16, 2022
9e99167
🧪Test: TDD를 적용한다. 미션(기존 커밋에 스탭이라고 표현했다)1에 대한 테스트 케이스를 작성한다.
InSeong-So Mar 16, 2022
9dae411
🎆Style: 템플릿 리터럴로 분리한 lotto-section을 정리하고 css를 추가한다.
InSeong-So Mar 18, 2022
b3a0554
✒️Feat: 로또 리스트 컴포넌트를 분리한다.
InSeong-So Mar 18, 2022
209611b
✒️Feat: 컴포넌트를 분리하고 템플릿/컨테이너로 기능을 구현한다.
InSeong-So Mar 19, 2022
56f1e05
🧪Test: 테스트 코드를 기능에 맞게 수정한다.
InSeong-So Mar 19, 2022
4e9c922
✒️Feat: 입력 금액에 대한 유효성 검사를 추가한다.
InSeong-So Mar 19, 2022
8e02929
🧺Remove: 잘못 커밋된 파일 제거
InSeong-So Mar 19, 2022
43a0a30
🎆Style: EOF 제거
InSeong-So Mar 19, 2022
061fb0d
🧪Test: 피드백을 반영하여 테스트 코드를 수정한다.
InSeong-So Mar 20, 2022
275fa6c
🗃Refactor: 서비스 로직을 일관되게 수정한다.
InSeong-So Mar 20, 2022
47aaae0
✒️Feat: isNil과 isEmpty를 추가하고 기존 함수를 수정한다.
InSeong-So Mar 20, 2022
4fe08c6
🗃Refactor: 중복되는 조건이 없도록 수정하고 상수화 된 에러메세지를 import 한다.
InSeong-So Mar 20, 2022
3c9d033
✒️Feat: 렌더링과 이벤트 바인딩을 담당할 함수를 커링을 활용하여 추가한다.
InSeong-So Mar 20, 2022
17c1d17
✒️Feat: 컴포넌트를 일관되게 작성하고 렌더링과 바인딩을 위임하는 함수를 호출하여 감싼다.
InSeong-So Mar 20, 2022
7ecbaeb
🗃Refactor: 수정된 컴포넌트에 따른 코드를 반영한다.
InSeong-So Mar 20, 2022
839354d
🧺Remove: 불필요 함수와 상수를 제거한다.
InSeong-So Mar 20, 2022
5b59910
fix: typo
pocojang Mar 21, 2022
0bbec63
✒️Feat: 3주차 클린코드 내용을 반영한다.
InSeong-So Mar 22, 2022
c40dab0
✒️Feat: 3주차 클린코드 내용을 반영한다.
InSeong-So Mar 22, 2022
55696ea
✒️Feat: 3주차 클린코드 내용을 반영한다.
InSeong-So Mar 22, 2022
2d29c31
🧪Test: 테스트 코드의 상수 경로를 수정한다.
InSeong-So Mar 22, 2022
87d33b2
🗃Refactor: 직관적인 네이밍으로 변경한다.
InSeong-So Mar 22, 2022
a3c58fd
🧪Test: 미션2에 대응하는 테스트 케이스 추가
InSeong-So Mar 27, 2022
f7d39d0
🎆Style: 모달 관련 css 수정
InSeong-So Mar 27, 2022
2ec92ef
✒️Feat: 모달 컴포넌트 추가
InSeong-So Mar 27, 2022
1ffff8f
✒️Feat: 유틸 함수 및 서비스 메세지 추가
InSeong-So Mar 27, 2022
3e21d90
🔬Chore: @babel-eslint 설정
InSeong-So Mar 27, 2022
e801bd0
✒️Feat: 컴포넌트 고도화
InSeong-So Mar 27, 2022
3942bb1
Merge branch 'inseong-so' into main
InSeong-So Mar 27, 2022
8c66837
Merge branch 'next-step:main' into main
InSeong-So Mar 27, 2022
0928de2
🗃Refactor: STEP2 1차 피드백 적용
InSeong-So Mar 29, 2022
ae9e588
🧺Remove: 불필요 파일 제거
InSeong-So Mar 29, 2022
aeca993
🗃Refactor: STEP2 2차 피드백 적용(함수 축약 표현 일관되게 적용)
InSeong-So Mar 29, 2022
5a3f204
🧪Test: STEP3 테스트 케이스 추가(시간 상 TDD 적용x)
InSeong-So Mar 30, 2022
8069441
🎆Style: STEP3 CSS 수정
InSeong-So Mar 30, 2022
2e12d27
✒️Feat: 수동 구매 모달 추가
InSeong-So Mar 30, 2022
64c1506
🗃Refactor: 당첨 결과 모달 수정
InSeong-So Mar 30, 2022
1d3dcc6
✒️Feat: 수동 구매 모달 추가에 따른 기능 수정
InSeong-So Mar 30, 2022
131d5a0
🗃Refactor: 당첨 번호 입력 수정
InSeong-So Mar 30, 2022
2fcc395
🗃Refactor: App, LottoList 수정
InSeong-So Mar 30, 2022
bd1fc51
Merge branch 'inseong-so' into main
InSeong-So Mar 30, 2022
6209e49
🔬Chore: git 에러로 인해 롤백
InSeong-So Mar 30, 2022
1555f9c
🛠Fix: 수동 구매를 하지 않을 수 있다.
InSeong-So Mar 31, 2022
f5daaa1
✒️Feat: 피드백 반영
InSeong-So Apr 2, 2022
7cfb7bb
🗃Refactor: HTML 기본 속성 활용하기(form elements)
InSeong-So Apr 2, 2022
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
53 changes: 53 additions & 0 deletions cypress/integration/app.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,59 @@ describe('Lotto', () => {
});

describe('로또 구입 금액이 정상인 경우', () => {
it('로또 구입 금액을 입력하면, 수동 구매 모달이 팝업되며 가격에 맞는 총 구매 가능한 개수가 출력된다.', () => {
cy.inputAmount('3000');
cy.get('.modal').should('be.visible');
cy.get('[data-props="available-count-h3"]').should('have.text', '총 3장 구매할 수 있어요!');
});

describe('수동 구매 개수가 비정상인 경우', () => {
it('수동 구매 개수는 총 구매 개수보다 많을 수 없다.', () => {
const alertStub = cy.stub();
cy.on('window:alert', alertStub);
cy.inputAmount('3000');
cy.get('[data-props="purchase-count-input"]').type('4');
cy.get('[data-props="purchase-count-button"]')
.click()
.then(() => {
expect(alertStub).to.be.calledWith(ERROR_MESSAGE.IMPOSSIBLE_COUNT);
});
});

it('수동 구매 개수는 0보다 작을 수 없다.', () => {
const alertStub = cy.stub();
cy.on('window:alert', alertStub);
cy.inputAmount('3000');
cy.get('[data-props="purchase-count-input"]').type('-1');
cy.get('[data-props="purchase-count-button"]')
.click()
.then(() => {
expect(alertStub).to.be.calledWith(ERROR_MESSAGE.IMPOSSIBLE_COUNT);
});
});

it('수동 구매 개수는 숫자 이외의 문자가 올 수 없다.', () => {
const alertStub = cy.stub();
cy.on('window:alert', alertStub);
cy.inputAmount('3000');
cy.get('[data-props="purchase-count-input"]').type('네개');
cy.get('[data-props="purchase-count-button"]')
.click()
.then(() => {
expect(alertStub).to.be.calledWith(ERROR_MESSAGE.REQUIRED_DIGIT);
});
});
});

describe('수동 구매 개수가 정상인 경우', () => {
it('수동 구매 개수만큼 로또 번호를 입력할 수 있어야 한다.', () => {
cy.inputAmount('3000');
cy.get('[data-props="purchase-count-input"]').type('1');
cy.get('[data-props="purchase-count-button"]').click();
cy.get('.scroll-area').should('be.visible');
});
});

it('로또 구입 금액을 입력하면, 금액에 해당하는 개수의 로또를 발급해야 한다.', () => {
cy.inputAmount('3000');
cy.get('.lotto-section').should('be.visible');
Expand Down
56 changes: 56 additions & 0 deletions src/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,60 @@ body {

svg {
pointer-events: none;
}

.asterisk {
color: red;
font-size: small;
}

[data-props="purchase-count-input"], [data-props="purchase-count-button"] {
height: 30px;
box-sizing: border-box;
}

[data-props="purchase-count-button"] {
padding: 1px 2px;
}

.purchase-number {
width: 30px;
height: 36px;
}

input[type="number"].purchase-number {
background-color: #c2f8ff;
border-color: #c2f8ff;
}

input[type="number"].purchase-number.bonus-number {
background-color: #00e1ff;
}

.scroll-area {
overflow-y: auto;
min-height: 200px;
max-height: 300px;
}

::-webkit-scrollbar {
width: 8px;
border-radius: 8px;
background-color: rgb(171, 224, 245);
}

::-webkit-scrollbar-thumb {
border: 2px solid rgba(0, 0, 0, 0);
background-clip: padding-box;
background-color: rgba(0, 0, 0, 0.15);
}

::-webkit-scrollbar-button {
width: 0;
height: 0;
display: none;
}

::-webkit-scrollbar-corner {
background-color: transparent;
}
4 changes: 4 additions & 0 deletions src/css/shared/modules/flex.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,7 @@
.order-none {
order: 0;
}

.gap-3 {
gap: 0.75rem; /* 12px */
}
4 changes: 4 additions & 0 deletions src/css/shared/modules/sizing.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
.w-100 {
width: 100%;
}

.max-w-none {
max-width: none !important;
}
59 changes: 12 additions & 47 deletions src/js/components/App.actions.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,23 @@
import { $, $elementRemoveClass, $allElementProp } from '../helper/index.js';
import LottoList from './lottoList/LottoList.js';
import LottoCheck from './lottoCheck/LottoCheck.js';
import LottoResultModal from './lottoResultModal/LottoResultModal.js';
import { $, $handleDOMError, $open } from '../helper/index.js';
import { LottoManualPurchase } from './modal/index.js';
import LottoService from '../services/Lotto.service.js';

export const inputAmount = event => {
export const handleSubmitAmount = event => {
event.preventDefault();

const $amountInput = $('[data-props="amount-input"]');
const $lottoSection = $('.lotto-section');
try {
const count = LottoService.validCount($amountInput.value);

const $lottoList = LottoList(count);
const $lottoCheck = LottoCheck();

$lottoSection.replaceChildren($lottoList, $lottoCheck);
$elementRemoveClass($lottoSection, 'hidden');
setModalContent($amountInput.value);
$open();
} catch (error) {
$amountInput.value = '';
alert(error.message);
$handleDOMError({ $amountInput, isReset: true, error });
}
};

export const toggleLottoResultModal = event => {
event.stopPropagation();
const $target = event.target;

if (LottoService.notingAction($target)) return;

const $modal = $('.modal');
function getModalContent(amount) {
return LottoManualPurchase(LottoService.validAmount(amount));
}

try {
if (LottoService.isLotteryOpen($target)) {
const purchasedNumbers = $allElementProp('.winning-number', 'value');
const lotteryResult = LottoService.lotteryResult(purchasedNumbers);
const $lottoResultModal = LottoResultModal(lotteryResult);
$modal.replaceChildren($lottoResultModal);
}
$modal.classList.toggle('open');
} catch (error) {
alert(error.message);
}
};

export const lottoRestart = ({ target }) => {
if (!target.matches('[data-props="restart-button"]')) return;

const $modal = $('.modal');
const $amountInput = $('[data-props="amount-input"]');
const $lottoSection = $('.lotto-section');

LottoService.initLottos();
$lottoSection.replaceChildren();
$amountInput.value = '';
$modal.classList.remove('open');
};
function setModalContent(amount) {
$('.modal').replaceChildren(getModalContent(amount));
}
8 changes: 2 additions & 6 deletions src/js/components/App.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { $eventBindedComponent } from '../helper/index.js';
import AppTemplate from './App.template.js';
import { inputAmount, toggleLottoResultModal, lottoRestart } from './App.actions.js';
import { handleSubmitAmount } from './App.actions.js';

const App = $eventBindedComponent(() => {
const $template = AppTemplate();
const $events = [
{ type: 'submit', callback: inputAmount },
{ type: 'click', callback: toggleLottoResultModal },
{ type: 'click', callback: lottoRestart },
];
const $events = [{ type: 'submit', callback: handleSubmitAmount }];

return [$template, $events];
});
Expand Down
10 changes: 4 additions & 6 deletions src/js/components/App.template.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { $elements } from '../helper/index.js';

const AppTemplate = () =>
$elements(
`
$elements(/*html*/ `
<div id="app" class="p-3">
<div class="d-flex justify-center mt-5" data-props="amount-info-form">
<div class="w-100">
Expand All @@ -11,16 +10,15 @@ const AppTemplate = () =>
<label class="mb-2 d-inline-block">구입할 금액을 입력해주세요.
</label>
<div class="d-flex">
<input type="text" class="w-100 mr-2 pl-2" data-props="amount-input" placeholder="구입 금액" />
<button type="submit" data-props="confirm-button" class="btn btn-cyan">확인</button>
<input type="text" class="w-100 mr-2 pl-2" name="amount-input" data-props="amount-input" placeholder="구입 금액" />
<button type="submit" data-props="confirm-button" class="open-purchase-modal-button btn btn-cyan">구매</button>
</div>
</form>
<div class="lotto-section hidden"></div>
</div>
</div>
<div class="modal"></div>
</div>
`,
);
`);

export default AppTemplate;
22 changes: 22 additions & 0 deletions src/js/components/lottoCheck/LottoCheck.actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { $, $allElementProp } from '../../helper/index.js';
import LottoService from '../../services/Lotto.service.js';
import { LottoResult } from '../modal/index.js';

export const toggleLottoResultModal = event => {
event.stopPropagation();
const $target = event.target;
if ($target.matches('.open-purchase-modal-button')) return;
if (LottoService.notingAction($target)) return;
const $modal = $('.modal');
try {
if (LottoService.isLotteryOpen($target)) {
const purchasedNumbers = $allElementProp('.winning-number', 'value');
const lotteryResult = LottoService.lotteryResult(purchasedNumbers);
const $lottoResult = LottoResult(lotteryResult);
$modal.replaceChildren($lottoResult);
}
$modal.classList.add('open');
} catch (error) {
alert(error.message);
}
};
9 changes: 6 additions & 3 deletions src/js/components/lottoCheck/LottoCheck.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { $eventBindedComponent } from '../../helper/dom.js';
import LottoCheckTemplate from './LottoCheck.template.js';
import { toggleLottoResultModal } from './LottoCheck.actions.js';

const LottoCheck = () => {
const LottoCheck = $eventBindedComponent(() => {
const $template = LottoCheckTemplate();
return $template;
};
const $events = [{ type: 'click', callback: toggleLottoResultModal }];
return [$template, $events];
});

export default LottoCheck;
2 changes: 1 addition & 1 deletion src/js/components/lottoCheck/LottoCheck.template.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { $elements } from '../../helper/index.js';

const LottoCheckTemplate = () => {
return $elements(`
return $elements(/*html*/ `
<form class="mt-9" data-props="compare-number-form">
<label class="flex-auto d-inline-block mb-3">지난 주 당첨번호 6개와 보너스 넘버 1개를 입력해주세요.</label>
<div class="d-flex" data-props="lotto-winning-numbers">
Expand Down
6 changes: 4 additions & 2 deletions src/js/components/lottoList/LottoList.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import LottoService from '../../services/Lotto.service.js';
import { toggleShowLottoNumber } from './LottoList.actions.js';
import LottoListTemplate from './LottoList.template.js';

const LottoList = $eventBindedComponent(count => {
const $template = LottoListTemplate({ numbers: LottoService.generatedLotto(count) });
const LottoList = $eventBindedComponent(manualPurchaseLotto => {
const $template = LottoListTemplate({
numbers: LottoService.generatedLotto(manualPurchaseLotto),
});
const $events = [
{
type: 'change',
Expand Down
4 changes: 2 additions & 2 deletions src/js/components/lottoList/LottoList.template.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { $elements } from '../../helper/index.js';

const LottoListTemplate = ({ numbers }) => {
return $elements(`
return $elements(/*html*/ `
${
numbers.length === 0
? ''
: `
: /*html*/ `
<section class="mt-9" data-props="lotto-wrapper-section">
<div class="d-flex">
<label class="flex-auto my-0">총 <span data-props="count-span">${
Expand Down
11 changes: 0 additions & 11 deletions src/js/components/lottoResultModal/LottoResultModal.js

This file was deleted.

2 changes: 2 additions & 0 deletions src/js/components/modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as LottoManualPurchase } from './lottoManualPurchase/LottoManualPurchase.js';
export { default as LottoResult } from './lottoResult/LottoResult.js';
Loading