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;
+ }
+ }
+}