From 06e2d1e5dfa781f7122ed5c482bd32fccb1218e4 Mon Sep 17 00:00:00 2001 From: Douglas Murita Date: Thu, 19 Sep 2024 22:32:04 -0300 Subject: [PATCH 1/4] feat: add markup --- src/layouts/pages/CreateAccount/index.js | 58 ++++++++ src/layouts/pages/CreateAccount/index.scss | 51 +++++++ src/layouts/pages/CreateAccount/index.spec.js | 125 ++++++++++++++++++ .../routes/app/main-routes/routes/account.js | 7 +- 4 files changed, 237 insertions(+), 4 deletions(-) create mode 100644 src/layouts/pages/CreateAccount/index.js create mode 100644 src/layouts/pages/CreateAccount/index.scss create mode 100644 src/layouts/pages/CreateAccount/index.spec.js diff --git a/src/layouts/pages/CreateAccount/index.js b/src/layouts/pages/CreateAccount/index.js new file mode 100644 index 00000000..648c1bb9 --- /dev/null +++ b/src/layouts/pages/CreateAccount/index.js @@ -0,0 +1,58 @@ +import { Component } from 'pet-dex-utilities'; +import Button from '~src/components/Button'; +import UploadImage from '../../../components/UploadImage'; + +import './index.scss'; + +const events = ['select:card', 'submit']; + +const html = ` +
+
+
+

Conta

+

Informações pessoais, email e senha

+
+
+
+
+ + + + +
+
+
+ +
+`; + +export default function CreateAccount() { + Component.call(this, { html, events }); + + // const $container = this.selected.get('container'); + const $footerContainer = this.selected.get('footer-container'); + const $uploadImage = this.selected.get('image-container'); + this.activeCard = null; + + const $button = new Button({ + text: 'Salvar', + isFullWidth: false, + isDisabled: true, + }); + + const $image = new UploadImage(); + $image.mount($uploadImage); + + $button.listen('click', () => { + this.emit('submit', { breedSelected: this.breedSelected }); + }); + + $button.selected.get('button').classList.add('breed-page__button'); + $button.mount($footerContainer); +} + +CreateAccount.prototype = Object.assign( + CreateAccount.prototype, + Component.prototype, +); diff --git a/src/layouts/pages/CreateAccount/index.scss b/src/layouts/pages/CreateAccount/index.scss new file mode 100644 index 00000000..012b9ae5 --- /dev/null +++ b/src/layouts/pages/CreateAccount/index.scss @@ -0,0 +1,51 @@ +@use '~styles/colors.scss' as colors; +@use '~styles/breakpoints.scss' as breakpoints; + +.breed-page { + height: 100%; + + display: flex; + flex-direction: column; + + &__breed-grid { + overflow: auto; + + display: flex; + flex-direction: column; + flex-wrap: wrap; + gap: 1.6rem; + + align-items: start; + + padding: 1rem; + } + + &__content { + padding: 2rem; + border: 1px solid rgb(104, 8, 8); + } + + &__footer { + width: 100%; + + display: flex; + + justify-content: center; + + margin-top: auto; + } + + &__button { + width: min(100%, 42rem); + } +} + +@include breakpoints.from1024 { + .breed-page { + &__breed-grid { + display: flex; + + align-items: center; + } + } +} diff --git a/src/layouts/pages/CreateAccount/index.spec.js b/src/layouts/pages/CreateAccount/index.spec.js new file mode 100644 index 00000000..e7821de0 --- /dev/null +++ b/src/layouts/pages/CreateAccount/index.spec.js @@ -0,0 +1,125 @@ +import { userEvent } from '@testing-library/user-event'; +import { render, screen } from '@testing-library/vanilla'; +import { describe, expect, it } from 'vitest'; + +import afghanHound from '~stories/assets/petRegisterPage/afghanHound.svg'; +import akita from '~stories/assets/petRegisterPage/akita.svg'; +import beagle from '~stories/assets/petRegisterPage/beagle.svg'; +import mixedBreed from '~stories/assets/petRegisterPage/mixedBreed.svg'; + +import PetRegisterPage from './index'; + +const renderPetRegisterPage = (parameters) => + render(new PetRegisterPage(parameters)); + +const mockCards = [ + { + title: 'Mixed Breed', + imgSrc: mixedBreed, + imgAlt: 'mixed breed', + }, + { + title: 'Akita', + imgSrc: akita, + imgAlt: 'akita', + }, + + { + title: 'Beagle', + imgSrc: beagle, + imgAlt: 'beagle', + }, + { + title: 'Afghan Hound', + imgSrc: afghanHound, + imgAlt: 'afghan hound', + }, +]; + +describe('PetRegisterPage', () => { + it('renders page with breeds', () => { + renderPetRegisterPage({ cards: mockCards }); + + const cardEvidence = screen.getByLabelText(/mixed breed/i); + const button = screen.getByRole('button'); + + expect(cardEvidence).toBeInTheDocument(); + expect(button).toBeInTheDocument(); + }); + + it('selects the pet when it is clicked', async () => { + const petRegister = renderPetRegisterPage({ cards: mockCards }); + const callback = vi.fn(); + + petRegister.listen('select:card', callback); + + const card = screen.getByLabelText(/mixed breed/i); + await userEvent.click(card); + + expect(callback).toHaveBeenCalled(); + expect(petRegister.activeCard).not.toBeNull(); + }); + + it('deselects the pet when it is clicked again', async () => { + const petRegister = renderPetRegisterPage({ cards: mockCards }); + + const callback = vi.fn(); + + petRegister.listen('select:card', callback); + + const card = screen.getByLabelText(/mixed breed/i); + await userEvent.click(card); + await userEvent.click(card); + + expect(petRegister.activeCard).toBeNull(); + }); + + it('deselects any previously selected card and selects the clicked one', async () => { + const petRegister = renderPetRegisterPage({ cards: mockCards }); + + const selectCard = vi.fn(); + + petRegister.listen('select:card', selectCard); + + const $afghanHoundCard = screen.getByLabelText(/afghan hound/i); + const $mixedBreedCard = screen.getByLabelText(/mixed breed/i); + + await userEvent.click($afghanHoundCard); + const mockAfghanHoundCard = petRegister.activeCard; + + await userEvent.click($mixedBreedCard); + const mixedBreedCard = petRegister.activeCard; + + expect(petRegister.activeCard).not.toBe(mockAfghanHoundCard); + expect(petRegister.activeCard).toBe(mixedBreedCard); + }); + + describe('emits', () => { + it('form data when every field is validated', async () => { + const petRegisterPage = renderPetRegisterPage({ cards: mockCards }); + const callBackEmit = vi.fn(); + petRegisterPage.listen('submit', callBackEmit); + + const mixedBreedCard = screen.getByLabelText(/mixed breed/i); + await userEvent.click(mixedBreedCard); + + const button = screen.getByRole('button'); + await userEvent.click(button); + + expect(callBackEmit).toHaveBeenCalledWith({ + breedSelected: 'Mixed Breed', + }); + }); + + it('does not happen when theres no card selected', async () => { + const petRegisterPage = renderPetRegisterPage({ cards: mockCards }); + const callBackEmit = vi.fn(); + petRegisterPage.listen('submit', callBackEmit); + + const button = screen.getByRole('button'); + await userEvent.click(button); + + expect(callBackEmit).not.toHaveBeenCalledWith('Mixed Breed'); + }); + }); +}); diff --git a/src/router/routes/app/main-routes/routes/account.js b/src/router/routes/app/main-routes/routes/account.js index 901ad359..2331646e 100644 --- a/src/router/routes/app/main-routes/routes/account.js +++ b/src/router/routes/app/main-routes/routes/account.js @@ -1,13 +1,12 @@ -import NoPetRegirestedPage from '~src/layouts/pages/NoPetRegirested'; +import CreateAccount from '~src/layouts/pages/CreateAccount'; export default { pathname: '/account', element: () => { const $content = document.createElement('div'); $content.classList.add('home__content-page'); - $content.style.backgroundColor = 'red'; - const noPetRegirestedPage = new NoPetRegirestedPage(); - noPetRegirestedPage.mount($content); + const createAccount = new CreateAccount(); + createAccount.mount($content); return $content; }, }; From cf2723488c6b19a40ef1bef61c92e1f57728b143 Mon Sep 17 00:00:00 2001 From: Douglas Murita Date: Tue, 24 Sep 2024 23:19:05 -0300 Subject: [PATCH 2/4] feat: add form markup --- src/layouts/pages/CreateAccount/index.js | 78 +++++++++++++++++++--- src/layouts/pages/CreateAccount/index.scss | 27 +++++++- 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/src/layouts/pages/CreateAccount/index.js b/src/layouts/pages/CreateAccount/index.js index 648c1bb9..bfef5882 100644 --- a/src/layouts/pages/CreateAccount/index.js +++ b/src/layouts/pages/CreateAccount/index.js @@ -1,5 +1,7 @@ import { Component } from 'pet-dex-utilities'; import Button from '~src/components/Button'; +import TextInput from '~src/components/TextInput'; +import Field from '~src/components/RegisterForm/components/Field'; import UploadImage from '../../../components/UploadImage'; import './index.scss'; @@ -15,11 +17,8 @@ const html = `
-
- - - - + +
@@ -31,23 +30,86 @@ export default function CreateAccount() { Component.call(this, { html, events }); // const $container = this.selected.get('container'); - const $footerContainer = this.selected.get('footer-container'); const $uploadImage = this.selected.get('image-container'); + const $field = this.selected.get('input-container'); + + const $footerContainer = this.selected.get('footer-container'); this.activeCard = null; + const name = new Field({ + label: 'Nome e Sobrenome', + error: 'Informe seu nome', + content: new TextInput({ + id: 'name', + placeholder: 'Informe seu nomes', + }), + }); + + const phone = new Field({ + label: 'Celular', + error: 'Devhat', + content: new TextInput({ + id: 'name', + placeholder: '(11) 12345-6789', + }), + }); + + const dataNascimento = new Field({ + label: 'Data de nascimento', + error: 'Informe seu nome', + content: new TextInput({ + id: 'name', + placeholder: '13/12/1995', + }), + }); + + const local = new Field({ + label: 'Local', + error: 'Informe seu celualr', + content: new TextInput({ + id: 'name', + placeholder: 'Sao Paulo, SP', + }), + }); + + const mail = new Field({ + label: 'E-mail', + error: 'Informe seu nome', + content: new TextInput({ + id: 'name', + placeholder: 'dev@devhat.com.br', + }), + }); + const password = new Field({ + label: 'Senha', + error: 'Informe seu nome', + content: new TextInput({ + id: 'name', + placeholder: '*******', + }), + }); + const $button = new Button({ text: 'Salvar', isFullWidth: false, isDisabled: true, }); - const $image = new UploadImage(); - $image.mount($uploadImage); + const $image = new UploadImage({}); $button.listen('click', () => { this.emit('submit', { breedSelected: this.breedSelected }); }); + $image.mount($uploadImage); + + name.mount($field); + phone.mount($field); + dataNascimento.mount($field); + local.mount($field); + mail.mount($field); + password.mount($field); + $button.selected.get('button').classList.add('breed-page__button'); $button.mount($footerContainer); } diff --git a/src/layouts/pages/CreateAccount/index.scss b/src/layouts/pages/CreateAccount/index.scss index 012b9ae5..218c5381 100644 --- a/src/layouts/pages/CreateAccount/index.scss +++ b/src/layouts/pages/CreateAccount/index.scss @@ -11,7 +11,7 @@ overflow: auto; display: flex; - flex-direction: column; + // flex-direction: column; flex-wrap: wrap; gap: 1.6rem; @@ -21,8 +21,31 @@ } &__content { + width: 100%; + + display: flex; + padding: 2rem; - border: 1px solid rgb(104, 8, 8); + + &_form { + width: min(100%, 70rem); + + height: 16rem; + + display: grid; + + grid-template-columns: repeat(2, 1fr); + + gap: 2rem; + + border: 2px dashed rgb(228, 4, 4); + } + } + + &__image { + width: min(100%, 18.6rem); + + margin: 4rem; } &__footer { From 699a7b8b3080482754e12b108c5da81680b06cf9 Mon Sep 17 00:00:00 2001 From: Douglas Murita Date: Wed, 25 Sep 2024 22:44:15 -0300 Subject: [PATCH 3/4] fix: form inputs --- src/layouts/pages/CreateAccount/index.js | 13 ++++- src/layouts/pages/CreateAccount/index.scss | 55 ++++++++++++++++++---- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/layouts/pages/CreateAccount/index.js b/src/layouts/pages/CreateAccount/index.js index bfef5882..83ebce05 100644 --- a/src/layouts/pages/CreateAccount/index.js +++ b/src/layouts/pages/CreateAccount/index.js @@ -18,7 +18,11 @@ const html = `
-
+
+ +
@@ -34,6 +38,9 @@ export default function CreateAccount() { const $field = this.selected.get('input-container'); const $footerContainer = this.selected.get('footer-container'); + + const $password = this.selected.get('link-password'); + this.activeCard = null; const name = new Field({ @@ -78,6 +85,7 @@ export default function CreateAccount() { content: new TextInput({ id: 'name', placeholder: 'dev@devhat.com.br', + type: 'mail', }), }); const password = new Field({ @@ -86,6 +94,7 @@ export default function CreateAccount() { content: new TextInput({ id: 'name', placeholder: '*******', + type: 'password', }), }); @@ -108,7 +117,7 @@ export default function CreateAccount() { dataNascimento.mount($field); local.mount($field); mail.mount($field); - password.mount($field); + password.mount($password); $button.selected.get('button').classList.add('breed-page__button'); $button.mount($footerContainer); diff --git a/src/layouts/pages/CreateAccount/index.scss b/src/layouts/pages/CreateAccount/index.scss index 218c5381..9300bb5b 100644 --- a/src/layouts/pages/CreateAccount/index.scss +++ b/src/layouts/pages/CreateAccount/index.scss @@ -1,17 +1,21 @@ @use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; @use '~styles/breakpoints.scss' as breakpoints; .breed-page { height: 100%; display: flex; + flex-direction: column; + font-family: fonts.$sixthFont; + &__breed-grid { overflow: auto; display: flex; - // flex-direction: column; + flex-wrap: wrap; gap: 1.6rem; @@ -20,25 +24,59 @@ padding: 1rem; } + &__header { + display: flex; + + flex-direction: column; + + gap: 1rem; + + padding: 2rem 5rem; + + > h1 { + color: colors.$primary700; + + font-size: fonts.$xl; + } + } + &__content { width: 100%; display: flex; - padding: 2rem; + gap: 4.2rem; + + padding: 5rem; &_form { - width: min(100%, 70rem); + width: 100%; + + > div { + width: 100%; + + display: grid; + + grid-template-columns: repeat(2, 1fr); + + gap: 2rem; + } + + .link-password { + width: 100%; - height: 16rem; + display: flex; - display: grid; + align-items: center; - grid-template-columns: repeat(2, 1fr); + justify-content: space-between; - gap: 2rem; + order: 1; - border: 2px dashed rgb(228, 4, 4); + > a { + order: 1; + } + } } } @@ -56,6 +94,7 @@ justify-content: center; margin-top: auto; + padding: 8rem 0; } &__button { From 42c00198933289199160e5ed6fa2b73cc2190e77 Mon Sep 17 00:00:00 2001 From: Douglas Murita Date: Mon, 30 Sep 2024 22:13:24 -0300 Subject: [PATCH 4/4] fix: type for inputs --- src/layouts/pages/CreateAccount/index.js | 66 +++++++++++++++++----- src/layouts/pages/CreateAccount/index.scss | 5 ++ 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/layouts/pages/CreateAccount/index.js b/src/layouts/pages/CreateAccount/index.js index 83ebce05..53291606 100644 --- a/src/layouts/pages/CreateAccount/index.js +++ b/src/layouts/pages/CreateAccount/index.js @@ -33,22 +33,20 @@ const html = ` export default function CreateAccount() { Component.call(this, { html, events }); - // const $container = this.selected.get('container'); const $uploadImage = this.selected.get('image-container'); const $field = this.selected.get('input-container'); - const $footerContainer = this.selected.get('footer-container'); - const $password = this.selected.get('link-password'); - this.activeCard = null; + this.activeForm = null; const name = new Field({ label: 'Nome e Sobrenome', error: 'Informe seu nome', content: new TextInput({ id: 'name', - placeholder: 'Informe seu nomes', + placeholder: 'Informe seu nome completo', + type: 'text', }), }); @@ -56,8 +54,9 @@ export default function CreateAccount() { label: 'Celular', error: 'Devhat', content: new TextInput({ - id: 'name', + id: 'phone', placeholder: '(11) 12345-6789', + type: 'number', }), }); @@ -65,34 +64,37 @@ export default function CreateAccount() { label: 'Data de nascimento', error: 'Informe seu nome', content: new TextInput({ - id: 'name', + id: 'nasc', placeholder: '13/12/1995', + type: 'date', }), }); const local = new Field({ label: 'Local', - error: 'Informe seu celualr', + error: 'Informe seu celular', content: new TextInput({ - id: 'name', + id: 'local', placeholder: 'Sao Paulo, SP', + type: 'text', }), }); const mail = new Field({ label: 'E-mail', - error: 'Informe seu nome', + error: 'Informe seu e-mail', content: new TextInput({ - id: 'name', + id: 'mail', placeholder: 'dev@devhat.com.br', type: 'mail', }), }); + const password = new Field({ label: 'Senha', - error: 'Informe seu nome', + error: 'Informe sua senha', content: new TextInput({ - id: 'name', + id: 'password', placeholder: '*******', type: 'password', }), @@ -106,8 +108,17 @@ export default function CreateAccount() { const $image = new UploadImage({}); + name.content.listen('value:change', () => { + if (this.activeForm) this.activeCard.deactivate(); + + this.emit('select:card', name); + $button.enable(); + }); + $button.listen('click', () => { - this.emit('submit', { breedSelected: this.breedSelected }); + // console.log('submitado', { name, phone, dataNascimento, local, mail, password }) + + this.emit('submit', { name, phone, dataNascimento, local, mail, password }); }); $image.mount($uploadImage); @@ -127,3 +138,30 @@ CreateAccount.prototype = Object.assign( CreateAccount.prototype, Component.prototype, ); + +// o submit do botao vai ser nesse estilo + +// const form = { +// isNeutered: undefined, +// isSpecialCare: undefined, +// specialCareText: '', +// vaccines: undefined, +// }; + +// const emitForm = () => { +// const neuteredValue = document.forms[0].elements.neutered.value; +// const specialCareValue = document.forms[1].elements.specialCare.value; +// const specialCareText = this.specialCareText.selected.get('textarea').value; + +// if (!neuteredValue || !specialCareValue) return; +// if (getBooleanValue(specialCareValue) && !specialCareText) return; + +// form.isNeutered = getBooleanValue(neuteredValue); +// form.isSpecialCare = getBooleanValue(specialCareValue); +// form.specialCareText = specialCareText; + +// form.vaccines = this.vaccine.listVaccines(); +// this.emit('submit', form); +// }; + +// this.button.listen('click', emitForm); diff --git a/src/layouts/pages/CreateAccount/index.scss b/src/layouts/pages/CreateAccount/index.scss index 9300bb5b..6e55f590 100644 --- a/src/layouts/pages/CreateAccount/index.scss +++ b/src/layouts/pages/CreateAccount/index.scss @@ -38,6 +38,11 @@ font-size: fonts.$xl; } + + > p { + color: colors.$gray600; + font-size: fonts.$sm; + } } &__content {