diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..57cccd7 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,22 @@ +module.exports = { + "env": { + "node": true, + "es6": true, + "browser": true + }, + "extends": "eslint:recommended", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "rules": { + "semi": [2, "never"], + "no-use-before-define": "off", + "no-underscore-dangle": "off", + "no-shadow": "off" + } +} diff --git a/mission003/eastjun/css/index.css b/mission003/eastjun/css/index.css new file mode 100644 index 0000000..714623f --- /dev/null +++ b/mission003/eastjun/css/index.css @@ -0,0 +1,178 @@ +/*mdc override*/ +:root { + --mdc-theme-primary: #333; +} + +.mdc-button__raised:not(:disabled), .mdc-button__unelevated:not(:disabled) { + background-color: var(--mdc-theme-primary,#333); +} + +.mdc-dialog__surface { + width: 400px; +} + +.mdc-card__actions { + padding: 0; +} + +.mdc-text-field { + margin: 10px auto; +} + +.mdc-dialog__actions { + padding-right: 0; +} +/*mdc override*/ + +body { + margin: 0; +} + +.background-img { + background-size: cover; + background-image: url("https://user-images.githubusercontent.com/56821976/71782829-d68f7000-3021-11ea-833d-9e286c629503.jpg"); + position: fixed; + width: 100%; + height: 50vh; +} + +.dark-overlay { + width: 100%; + background-color: rgba(0,0,0,.2); + height: 50vh; + z-index: 10; +} + +.signup-card { + max-width: 400px; + margin: 100px auto; +} + +.signup-card h2{ + margin-top: 32px; +} + +form.signup { + padding: 24px; +} + +.text-center { + text-align: center; +} + +.hidden { + display: none; +} + +.bullet-o{ + display: flex; + flex-flow: row wrap; + justify-content: center; +} + +.bullet-o > div{ + height: 15px; + width: 15px; + margin: 20px 10px; + border-radius: 100px; + z-index: 2; +} + +.bullet{ + background-color: lightgrey; + +} + +.bullet-active{ + background-color: #333 !important; +} + +.bullet-line{ + opacity: 0.3; + background: lightgrey; + height: 3px; + width: 70px; + display: block; + left: 50%; + margin-top: -29px; + margin-left: -35px; + position: absolute; + z-index: 1; +} + +.pdd-top-0 { + padding-top: 0px !important; +} + +.width-100 { + width: 100%; +} + +.flex-container { + display: flex; +} + +.mrg-right-10 { + margin-right: 10px; +} + +#add-family-button { + display: block; + margin: 0 auto; +} + +.stepper { + position: relative; +} + +.coffee-emoji { + font-size: 100px; + margin: 40px 0 70px 0; +} + +.margin-center { + margin: 0% auto; +} + +.my-info-view-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; +} + +.text-bold { + font-weight: bold; +} + +.my-info { + padding: 30px; +} + +.my-info-card { + width: 400px; + padding: 30px; + position: relative; +} + +#my-info-edit-button { + top: 16px; + right: 16px; + position: absolute; +} + +.no-margin { + margin: 0px; +} + +.margin-16 { + margin: 16px; +} + +.margin-8 { + margin: 8px; +} + +.text-gray { + color: gray; +} diff --git a/mission003/eastjun/index.html b/mission003/eastjun/index.html new file mode 100644 index 0000000..d09f2a0 --- /dev/null +++ b/mission003/eastjun/index.html @@ -0,0 +1,134 @@ + + + + + mission003 + + + + + + + +
+
+
+
+ +
+
+
+

회원가입

+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + + + diff --git a/mission003/eastjun/js/App.js b/mission003/eastjun/js/App.js new file mode 100644 index 0000000..d07dc0d --- /dev/null +++ b/mission003/eastjun/js/App.js @@ -0,0 +1,18 @@ +import Form from './components/Form.js' +import User from './components/User.js' +function FormApp() { + this.user = new User() + this.mdcInit = () => mdc.autoInit() + + this.init = () => { + new Form({ + mdcInit: this.mdcInit, + user: this.user + }) + this.mdcInit() + } + + this.init() +} + +new FormApp() diff --git a/mission003/eastjun/js/components/Family.js b/mission003/eastjun/js/components/Family.js new file mode 100644 index 0000000..5b4d1fa --- /dev/null +++ b/mission003/eastjun/js/components/Family.js @@ -0,0 +1,8 @@ +import { familyFormTemplate } from '../utils/templates.js' + +export default function Family() { + this.name = '' + this.relations = '' + + this.render = (index) => familyFormTemplate(index) +} diff --git a/mission003/eastjun/js/components/Form.js b/mission003/eastjun/js/components/Form.js new file mode 100644 index 0000000..e776f98 --- /dev/null +++ b/mission003/eastjun/js/components/Form.js @@ -0,0 +1,199 @@ +import validator from '../utils/validator.js' +import { familyFormField } from '../utils/constants.js' +import Family from './Family.js' +import { myInfoViewTemplate, familyViewTemplate } from '../utils/templates.js' + +export default function Form({ mdcInit, user }) { + this.isAgreement = false + this.dialog = new mdc.dialog.MDCDialog(document.querySelector('.mdc-dialog')) + + const $formTitle = document.querySelector('#my-dialog-title') + + const addFamilyFieldTemplate = (event) => { + event.preventDefault() + const family = new Family() + user.addFamily(family) + const lastIndex = user.family.length - 1 + const $familyForm = document.querySelector('.user-family-forms') + $familyForm.insertAdjacentHTML('beforeend', family.render(lastIndex)) + mdcInit() + } + + const isFilledForm = () => { + const $step1CompleteButton = document.querySelector('.step1-complete-btn') + + if (this.isAgreement && user.isBasicInfoNotEmpty()) { + $step1CompleteButton.classList.remove('hidden') + $step1CompleteButton.addEventListener('click', activeStep2) + return + } + $step1CompleteButton.classList.add('hidden') + } + + const step1 = () => { + const $step1TabClassList = document.querySelector('#step1').classList + const $bullet1ClassList = document.querySelector('.bullet1').classList + const $agreementClassList = document.querySelector('.privacy-policy-agree-container').classList + + const active = () => { + $step1TabClassList.remove('hidden') + $bullet1ClassList.add('bullet-active') + } + + const inActive = () => { + $step1TabClassList.add('hidden') + $bullet1ClassList.remove('bullet-active') + } + + const togglePrivacyCheckbox = (value) => { + validator.isEmptyString(value) ? $agreementClassList.add('hidden') : $agreementClassList.remove('hidden') + } + + return { + active, + inActive, + togglePrivacyCheckbox + } + } + + const step2 = () => { + const $step2TabClassList = document.querySelector('#step2').classList + const $bullet2ClassList = document.querySelector('.bullet2').classList + + const active = () => { + $step2TabClassList.remove('hidden') + $bullet2ClassList.add('bullet-active') + } + + const inActive = () => { + $step2TabClassList.add('hidden') + $bullet2ClassList.remove('bullet-active') + } + + return { + active, + inActive + } + } + + const step3 = () => { + const $step3TabClassList = document.querySelector('#step3').classList + const $bullet3ClassList = document.querySelector('.bullet3').classList + + const active = () => { + $step3TabClassList.remove('hidden') + $bullet3ClassList.add('bullet-active') + } + + const inActive = () => { + $step3TabClassList.add('hidden') + $bullet3ClassList.remove('bullet-active') + } + + const renderViewCard = () => { + document.querySelector('#my-info-view-card').innerHTML = myInfoViewTemplate(user) + const myFamilyInfoTemplate = user.family.map((member) => familyViewTemplate(member)).join('') + document.querySelector('.my-family-list-container').innerHTML = myFamilyInfoTemplate + const $myInfoEditButton = document.querySelector('#my-info-edit-button') + $myInfoEditButton.addEventListener('click', showEditDialog) + } + + const showEditDialog = () => { + activeStep1() + this.dialog.open() + } + + return { + active, + inActive, + renderViewCard + } + } + + const activeStep1 = () => { + step3().inActive() + step2().inActive() + step1().active() + } + + const activeStep2 = (event) => { + event.preventDefault() + step1().inActive() + step2().active() + $formTitle.innerText = '가족 구성원 입력' + } + + const activeStep3 = (event) => { + event.preventDefault() + step2().inActive() + step3().active() + step3().renderViewCard() + $formTitle.innerText = '업데이트 완료' + } + + this.update = { + name: (event) => { + user.update.name(event.target.value) + isFilledForm() + }, + phone: (event) => { + const phone = event.target.value + user.update.phone(event.target.value) + step1().togglePrivacyCheckbox(phone) + isFilledForm() + }, + email: (event) => { + const email = event.target.value + user.update.email(email) + step1().togglePrivacyCheckbox(email) + isFilledForm() + }, + password: (event) => { + user.update.password(event.target.value) + isFilledForm() + }, + introduce: (event) => { + user.update.introduce(event.target.value) + isFilledForm() + }, + agreement: (event) => { + this.isAgreement = event.target.checked + isFilledForm() + }, + family: (event) => { + const index = event.target.closest('.user-family-form-fields').dataset.index + const inputName = event.target.name + const value = event.target.value + + switch (inputName) { + case familyFormField.NAME: + user.update.family.name(index, value) + break + case familyFormField.RELATIONS: + user.update.family.relations(index, value) + break + default: + break + } + } + } + + this.initEventListener = () => { + document.querySelector('#name').addEventListener('keyup', this.update.name) + document.querySelector('#phone').addEventListener('keyup', this.update.phone) + document.querySelector('#email').addEventListener('keyup', this.update.email) + document.querySelector('#password').addEventListener('keyup', this.update.password) + document.querySelector('#introduce').addEventListener('keyup', this.update.introduce) + document.querySelector('#agreement').addEventListener('click', this.update.agreement) + document.querySelector('#add-family-button').addEventListener('click', addFamilyFieldTemplate) + document.querySelector('.user-family-forms').addEventListener('keyup', this.update.family) + document.querySelector('form.signup').addEventListener('submit', activeStep3) + } + + this.init = () => { + this.dialog.open() + this.initEventListener() + } + + this.init() +} diff --git a/mission003/eastjun/js/components/User.js b/mission003/eastjun/js/components/User.js new file mode 100644 index 0000000..10d045f --- /dev/null +++ b/mission003/eastjun/js/components/User.js @@ -0,0 +1,34 @@ +import validator from '../utils/validator.js' + +export default function User() { + this.name = '' + this.email = '' + this.phone = '' + this.password = '' + this.introduce = '' + this.family = [] + + this.update = { + name: (name) => this.name = name, + email: (email) => this.email = email, + phone: (phone) => this.phone = phone, + password: (password) => this.password = password, + introduce: (introduce) => this.introduce = introduce, + family: { + name: (index, name) => this.family[index].name = name, + relations: (index, relations) => this.family[index].relations = relations + } + } + + this.addFamily = (member) => this.family.push(member) + + this.isBasicInfoNotEmpty = () => { + if (validator.isNotEmptyString(this.name) && + validator.isNotEmptyString(this.email) && + validator.isNotEmptyString(this.phone) && + validator.isNotEmptyString(this.password) && + validator.isNotEmptyString(this.introduce)) { + return true + } + } +} diff --git a/mission003/eastjun/js/utils/constants.js b/mission003/eastjun/js/utils/constants.js new file mode 100644 index 0000000..5578bad --- /dev/null +++ b/mission003/eastjun/js/utils/constants.js @@ -0,0 +1,5 @@ +const familyFormField = { + NAME: 'family-name', + RELATIONS: 'family-relations' +} +export { familyFormField } diff --git a/mission003/eastjun/js/utils/templates.js b/mission003/eastjun/js/utils/templates.js new file mode 100644 index 0000000..d5713b9 --- /dev/null +++ b/mission003/eastjun/js/utils/templates.js @@ -0,0 +1,56 @@ +const familyFormTemplate = (index) => ` +
+
+ + +
+
+
+ + +
+
+
` + +const familyViewTemplate = (family) => ` +
+ ${family.name} (${family.relations}) +
` + +const myInfoViewTemplate = (formFields) => ` +
+
+ +
+

나의 정보

+
+
+
이름
+
${formFields.name}
+
+
+
이메일
+
${formFields.email}
+
+
+
전화번호
+
${formFields.phone}
+
+
+
소개
+
${formFields.introduce}
+
+
+
가족
+
+
+
+
+
+
` + +export { + familyFormTemplate, + myInfoViewTemplate, + familyViewTemplate +} diff --git a/mission003/eastjun/js/utils/validator.js b/mission003/eastjun/js/utils/validator.js new file mode 100644 index 0000000..77b4bfa --- /dev/null +++ b/mission003/eastjun/js/utils/validator.js @@ -0,0 +1,13 @@ +const validator = { + isString(str) { + return typeof str === 'string' || str instanceof String + }, + isEmptyString(str) { + return (!str || 0 === str.length) + }, + isNotEmptyString(str) { + return (this.isString(str) && str.length > 0) + }, +} + +export default validator diff --git a/package.json b/package.json new file mode 100644 index 0000000..f5029c0 --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "frontend", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/EastjunDev/frontend.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/EastjunDev/frontend/issues" + }, + "homepage": "https://github.com/EastjunDev/frontend#readme", + "devDependencies": { + "babel-eslint": "^10.0.3", + "eslint": "^5.16.0", + "eslint-config-airbnb-base": "^14.0.0", + "eslint-config-standard": "^14.1.0", + "eslint-plugin-html": "^6.0.0", + "eslint-plugin-import": "^2.19.1", + "eslint-plugin-node": "^10.0.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1", + "eslint-plugin-vue": "^6.0.1" + } +}