diff --git a/src/app/App/view/appView.module.scss b/src/app/App/view/appView.module.scss index e69de29b..d99b27c9 100644 --- a/src/app/App/view/appView.module.scss +++ b/src/app/App/view/appView.module.scss @@ -0,0 +1,7 @@ +.siteWrapper { + display: flex; + flex-direction: column; + justify-content: space-between; + width: 100%; + min-height: 100vh; +} diff --git a/src/app/styles/variables.scss b/src/app/styles/variables.scss index f5b4bfe7..2d710107 100644 --- a/src/app/styles/variables.scss +++ b/src/app/styles/variables.scss @@ -4,6 +4,7 @@ --small-offset: 40px; --medium-offset: 60px; --large-offset: 80px; + --extra-large-offset: 100px; // border-radius --small-br: 5px; @@ -14,6 +15,7 @@ --white: #fff; --black: #000; --noble-white-100: #f5f5f5; + --noble-gray-200: #eaeaea; --noble-gray-300: #cbcbcb; --noble-gray-400: #c4c4c4; --noble-gray-500: #acacac; @@ -23,14 +25,15 @@ --red-power-600: #d0302f; --steam-green-400: #c8f4b4; --steam-green-500: #b6f09c; + --steam-green-700: #70d27a; --steam-green-800: #46a358; // fonts - --regular-font: 400 16px 'Cerapro', sans-serif; + --regular-font: 400 13px 'Cerapro', sans-serif; --extra-regular-font: 400 24px 'Cerapro', sans-serif; - --medium-font: 500 24px 'Cerapro', sans-serif; + --medium-font: 500 20px 'Cerapro', sans-serif; --extra-medium-font: 500 30px 'Cerapro', sans-serif; - --bold-font: 700 30px 'Cerapro', sans-serif; + --bold-font: 700 16px 'Cerapro', sans-serif; --extra-bold-font: 700 35px 'Cerapro', sans-serif; --black-font: 900 35px 'Cerapro', sans-serif; --extra-black-font: 900 40px 'Cerapro', sans-serif; @@ -40,7 +43,8 @@ --small-offset: 20px; --medium-offset: 30px; --large-offset: 40px; - --small-br: 2px; + --extra-large-offset: 50px; + --small-br: 5px; --medium-br: 5px; --large-br: 10px; } diff --git a/src/entities/InputField/view/InputFieldView.ts b/src/entities/InputField/view/InputFieldView.ts index 531b03f9..069de0c4 100644 --- a/src/entities/InputField/view/InputFieldView.ts +++ b/src/entities/InputField/view/InputFieldView.ts @@ -1,12 +1,11 @@ import type { InputFieldParams, InputParams, LabelParams } from '@/shared/types/interfaces.ts'; import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; +import InputModel from '@/shared/Input/model/InputModel.ts'; import { INPUT_TYPES, SVG_DETAILS, TAG_NAMES } from '@/shared/constants/enums.ts'; import createBaseElement from '@/shared/utils/createBaseElement.ts'; import createSVGUse from '@/shared/utils/createSVGUse.ts'; -import InputModel from '@/shared/Input/model/InputModel.ts'; - class InputFieldView { private errorField: HTMLSpanElement | null = null; diff --git a/src/pages/LoginPage/model/LoginPageModel.ts b/src/pages/LoginPage/model/LoginPageModel.ts index 6dd5d577..e1c3f38e 100644 --- a/src/pages/LoginPage/model/LoginPageModel.ts +++ b/src/pages/LoginPage/model/LoginPageModel.ts @@ -15,7 +15,7 @@ class LoginPageModel implements PageInterface { } private init(): boolean { - this.getHTML().append(this.loginForm.getHTML()); + this.view.getAuthWrapper().append(this.loginForm.getHTML()); return true; } diff --git a/src/pages/LoginPage/view/LoginPageView.ts b/src/pages/LoginPage/view/LoginPageView.ts index 6f2e7b3d..35269d6d 100644 --- a/src/pages/LoginPage/view/LoginPageView.ts +++ b/src/pages/LoginPage/view/LoginPageView.ts @@ -1,29 +1,102 @@ -import { TAG_NAMES } from '@/shared/constants/enums.ts'; +import { PAGE_DESCRIPTION, PAGE_LINK_TEXT, PAGES_IDS, TAG_NAMES } from '@/shared/constants/enums.ts'; import createBaseElement from '@/shared/utils/createBaseElement.ts'; import LOGIN_PAGE_STYLES from './loginPageView.module.scss'; class LoginPageView { + private authDescription: HTMLHeadingElement; + + private authWrapper: HTMLDivElement; + + private linksWrapper: HTMLDivElement; + + private loginSpan: HTMLSpanElement; + private page: HTMLDivElement; private parent: HTMLDivElement; + private registerLink: HTMLAnchorElement; + constructor(parent: HTMLDivElement) { this.parent = parent; + this.loginSpan = this.createLoginSpan(); + this.registerLink = this.createRegisterLink(); + this.authDescription = this.createAuthDescription(); + this.linksWrapper = this.createLinksWrapper(); + this.authWrapper = this.createAuthWrapper(); this.page = this.createHTML(); } + private createAuthDescription(): HTMLHeadingElement { + this.authDescription = createBaseElement({ + cssClasses: [LOGIN_PAGE_STYLES.authDescription], + innerContent: PAGE_DESCRIPTION.LOGIN, + tag: TAG_NAMES.H3, + }); + + return this.authDescription; + } + + private createAuthWrapper(): HTMLDivElement { + this.authWrapper = createBaseElement({ + cssClasses: [LOGIN_PAGE_STYLES.authWrapper], + tag: TAG_NAMES.DIV, + }); + + this.authWrapper.append(this.linksWrapper, this.authDescription); + return this.authWrapper; + } + private createHTML(): HTMLDivElement { this.page = createBaseElement({ cssClasses: [LOGIN_PAGE_STYLES.loginPage], tag: TAG_NAMES.DIV, }); + this.page.append(this.authWrapper); this.parent.append(this.page); return this.page; } + private createLinksWrapper(): HTMLDivElement { + this.linksWrapper = createBaseElement({ + cssClasses: [LOGIN_PAGE_STYLES.linksWrapper], + tag: TAG_NAMES.DIV, + }); + + this.linksWrapper.append(this.loginSpan, this.registerLink); + return this.linksWrapper; + } + + private createLoginSpan(): HTMLSpanElement { + this.loginSpan = createBaseElement({ + cssClasses: [LOGIN_PAGE_STYLES.loginSpan], + innerContent: PAGE_LINK_TEXT.LOGIN, + tag: TAG_NAMES.SPAN, + }); + + return this.loginSpan; + } + + private createRegisterLink(): HTMLAnchorElement { + this.registerLink = createBaseElement({ + attributes: { + href: PAGES_IDS.REGISTRATION_PAGE, + }, + cssClasses: [LOGIN_PAGE_STYLES.registerLink], + innerContent: PAGE_LINK_TEXT.REGISTRATION, + tag: TAG_NAMES.A, + }); + + return this.registerLink; + } + + public getAuthWrapper(): HTMLDivElement { + return this.authWrapper; + } + public getHTML(): HTMLDivElement { return this.page; } diff --git a/src/pages/LoginPage/view/loginPageView.module.scss b/src/pages/LoginPage/view/loginPageView.module.scss index e69de29b..6385d44d 100644 --- a/src/pages/LoginPage/view/loginPageView.module.scss +++ b/src/pages/LoginPage/view/loginPageView.module.scss @@ -0,0 +1,88 @@ +.loginPage { + position: relative; + display: block; + padding: 0 var(--small-offset); + + &_hidden { + display: none; + } +} + +.authWrapper { + margin: 0 auto; + border-bottom: 10px solid var(--steam-green-800); + padding: calc(var(--extra-large-offset) / 2) var(--extra-large-offset); + max-width: 500px; + background-color: var(--white); +} + +.linksWrapper { + position: relative; + display: flex; + align-self: center; + justify-content: space-between; + margin: 0 auto; + margin-bottom: calc(var(--extra-large-offset) / 2); + max-width: 160px; + + &::after { + content: ''; + position: absolute; + right: calc(50% - 3px); + top: 50%; + width: 3px; + height: 16px; + background-color: var(--noble-gray-800); + transform: translate(calc(-50% - 14px), -50%); + } +} + +.loginSpan, +.registerLink { + font: var(--medium-font); + letter-spacing: 1px; +} + +.loginSpan { + color: var(--steam-green-800); +} + +.registerLink { + position: relative; + color: var(--noble-gray-800); + transition: color 0.2s; + + &::after { + content: ''; + position: absolute; + left: 0; + bottom: -4px; + width: 100%; + height: 2px; + background-color: currentcolor; + opacity: 0; + transform: scaleX(0); + transform-origin: center; + transition: + transform 0.2s, + opacity 0.2s; + } + + @media (hover: hover) { + &:hover { + color: var(--steam-green-800); + + &::after { + opacity: 1; + transform: scaleX(1); + } + } + } +} + +.authDescription { + margin-bottom: calc(var(--extra-small-offset) / 2); + font: var(--regular-font); + letter-spacing: 1px; + text-align: center; +} diff --git a/src/pages/MainPage/view/mainPageView.module.scss b/src/pages/MainPage/view/mainPageView.module.scss index e69de29b..7abd98eb 100644 --- a/src/pages/MainPage/view/mainPageView.module.scss +++ b/src/pages/MainPage/view/mainPageView.module.scss @@ -0,0 +1,9 @@ +.mainPage { + position: relative; + display: block; + padding: 0 var(--small-offset); + + &_hidden { + display: none; + } +} diff --git a/src/pages/NotFoundPage/view/notFoundPageView.module.scss b/src/pages/NotFoundPage/view/notFoundPageView.module.scss index e69de29b..0dd6bd7f 100644 --- a/src/pages/NotFoundPage/view/notFoundPageView.module.scss +++ b/src/pages/NotFoundPage/view/notFoundPageView.module.scss @@ -0,0 +1,9 @@ +.notFoundPage { + position: relative; + display: block; + padding: 0 var(--small-offset); + + &_hidden { + display: none; + } +} diff --git a/src/pages/RegistrationPage/view/registrationPageView.module.scss b/src/pages/RegistrationPage/view/registrationPageView.module.scss index e69de29b..12508f19 100644 --- a/src/pages/RegistrationPage/view/registrationPageView.module.scss +++ b/src/pages/RegistrationPage/view/registrationPageView.module.scss @@ -0,0 +1,9 @@ +.registrationPage { + position: relative; + display: block; + padding: 0 var(--small-offset); + + &_hidden { + display: none; + } +} diff --git a/src/shared/constants/enums.ts b/src/shared/constants/enums.ts index d8b9e6dc..12148274 100644 --- a/src/shared/constants/enums.ts +++ b/src/shared/constants/enums.ts @@ -123,7 +123,7 @@ export const LOGIN_FORM_EMAIL_FIELD_PARAMS = { }, labelParams: { for: 'email', - text: 'Enter your email', + text: '', }, } as const; @@ -136,7 +136,7 @@ export const LOGIN_FORM_PASSWORD_FIELD_PARAMS = { }, labelParams: { for: 'password', - text: 'Enter your password', + text: '', }, } as const; @@ -184,3 +184,13 @@ export const SVG_DETAILS = { OPEN_EYE: 'openEye', SVG_URL: 'http://www.w3.org/2000/svg', } as const; + +export const PAGE_LINK_TEXT = { + LOGIN: 'Login', + MAIN: 'Main', + REGISTRATION: 'Register', +} as const; + +export const PAGE_DESCRIPTION = { + LOGIN: 'Enter your email and password to register.', +} as const; diff --git a/src/shared/img/svg/closeEye.svg b/src/shared/img/svg/closeEye.svg index 3462ccbe..36cdc7af 100644 --- a/src/shared/img/svg/closeEye.svg +++ b/src/shared/img/svg/closeEye.svg @@ -1,3 +1,3 @@ - + diff --git a/src/shared/img/svg/openEye.svg b/src/shared/img/svg/openEye.svg index 6d8f9724..5f4f6d68 100644 --- a/src/shared/img/svg/openEye.svg +++ b/src/shared/img/svg/openEye.svg @@ -1,4 +1,4 @@ - - + + diff --git a/src/widgets/LoginForm/model/LoginFormModel.ts b/src/widgets/LoginForm/model/LoginFormModel.ts index 68566c72..f6907071 100644 --- a/src/widgets/LoginForm/model/LoginFormModel.ts +++ b/src/widgets/LoginForm/model/LoginFormModel.ts @@ -1,7 +1,7 @@ -import { EVENT_NAMES } from '@/shared/constants/enums.ts'; - import type InputFieldModel from '@/entities/InputField/model/InputFieldModel.ts'; +import { EVENT_NAMES } from '@/shared/constants/enums.ts'; + import LoginFormView from '../view/LoginFormView.ts'; class LoginFormModel { diff --git a/src/widgets/LoginForm/view/loginForm.module.scss b/src/widgets/LoginForm/view/loginForm.module.scss index e69de29b..fd45dad0 100644 --- a/src/widgets/LoginForm/view/loginForm.module.scss +++ b/src/widgets/LoginForm/view/loginForm.module.scss @@ -0,0 +1,102 @@ +.loginForm { + display: flex; + flex-direction: column; + margin: 0 auto; + gap: var(--extra-small-offset); + + label { + position: relative; + display: flex; + flex-direction: column; + gap: calc(var(--extra-small-offset) / 2); + + button { + position: absolute; + right: 0; + top: 7px; + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 8); + width: 24px; + height: 24px; + background-color: transparent; + transform: translate(-12%, 0); + + svg { + width: 20px; + height: 20px; + stroke: var(--noble-gray-600); + transition: stroke 0.2s; + } + + @media (hover: hover) { + &:hover { + background-color: var(--noble-gray-200); + + svg { + stroke: var(--steam-green-800); + } + } + } + } + + @media (max-width: 768px) { + button { + top: 2px; + } + } + } + + input { + border: 1px solid var(--noble-gray-200); + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--extra-small-offset); + font: var(--regular-font); + letter-spacing: 1px; + color: var(--noble-gray-800); + transition: border 0.2s; + + &::placeholder { + color: var(--noble-gray-600); + } + + &:focus { + border: 1px solid var(--steam-green-800); + } + + @media (hover: hover) { + &:hover { + border: 1px solid var(--steam-green-800); + } + } + } + + span { + font: var(--regular-font); + letter-spacing: 1px; + text-align: center; + color: var(--red-power-600); + } + + button { + border-radius: var(--small-br); + padding: calc(var(--extra-small-offset) / 2) var(--small-offset); + font: var(--bold-font); + letter-spacing: 1px; + color: var(--white); + background-color: var(--steam-green-800); + transition: + color 0.2s, + background-color 0.2s; + + @media (hover: hover) { + &:hover { + background-color: var(--steam-green-700); + } + } + + &:disabled { + background-color: var(--noble-gray-300); + pointer-events: none; + } + } +}