Skip to content

Commit 06a054b

Browse files
implement login, logout, registration flows (#22)
* implement login, logout, registration flows * move AppHeaderLogin component before the Shopkit Cart * add formik lib, use the global hook to get customer data * add validation, rename components, define return types, show dropdown on click * update failure login message * update style of buttons on the login form
1 parent 9c3bc75 commit 06a054b

18 files changed

+893
-10
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
"constate": "^2.0.0",
1313
"css-reset-and-normalize": "^2.1.0",
1414
"eslint-plugin-jsx-a11y": "^6.3.1",
15+
"formik": "^2.1.4",
1516
"node-sass": "^4.13.0",
1617
"react": "^16.13.1",
1718
"react-axe": "^3.5.2",
1819
"react-cool-onclickoutside": "^1.5.2",
1920
"react-dom": "^16.13.1",
21+
"react-responsive-modal": "^4.0.1",
2022
"react-router-dom": "^5.2.0",
2123
"react-script-hook": "^1.1.1",
2224
"react-scripts": "3.4.1",

src/AccountDropdown.scss

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
2+
@import './theme/common.scss';
3+
4+
.accountdropdown {
5+
position: relative;
6+
7+
&__btn {
8+
padding: 5px;
9+
cursor: pointer;
10+
11+
&:after {
12+
display: inline-block;
13+
content: ' ';
14+
width: 8px;
15+
height: 8px;
16+
border: none;
17+
border-left: 1.5px solid $mainColor;
18+
border-bottom: 1.5px solid $mainColor;
19+
transform-origin: center;
20+
transform: rotate(-45deg);
21+
vertical-align: middle;
22+
}
23+
}
24+
25+
&__btnicon {
26+
display: inline-block;
27+
content: " ";
28+
width: 25px;
29+
height: 21px;
30+
background-size: cover;
31+
margin-right: 5px;
32+
}
33+
34+
&__menu {
35+
padding: 10px 10px 15px;
36+
position: absolute;
37+
right: 0;
38+
top: 100%;
39+
background-color: $mainBackgroundColor;
40+
z-index: 1;
41+
min-width: 200px;
42+
border: 1px solid $secondComplimentColor;
43+
}
44+
45+
&__link {
46+
width: 100%;
47+
display: inline-block;
48+
padding: 7px 0;
49+
color: $thirdComplimentColor;
50+
font-size: 13px;
51+
line-height: 19px;
52+
}
53+
54+
&__iteminfo {
55+
font-size: 13px;
56+
font-weight: bold;
57+
}
58+
59+
&__emailinfo {
60+
font-size: 12px;
61+
font-style: italic;
62+
color: $firstComplimentTextColor;
63+
}
64+
65+
&__itemtitle {
66+
padding-bottom: 5px;
67+
margin-bottom: 5px;
68+
border-bottom: 1px solid $fifthComplimentTextColor;
69+
}
70+
71+
&__itembtns {
72+
margin-top: 5px;
73+
}
74+
75+
&__open & {
76+
&__btn {
77+
&:after {
78+
transform: rotate(135deg);
79+
border-left-color: $thirdComplimentColor;
80+
border-bottom-color: $thirdComplimentColor;
81+
margin-top: 5px;
82+
}
83+
}
84+
85+
&__btnicon {
86+
fill: $thirdComplimentColor;
87+
}
88+
}
89+
90+
&__loginbtn{
91+
color: $mainTextColor;
92+
cursor: pointer;
93+
}
94+
}

src/AccountDropdown.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
import React, { useState} from 'react';
3+
// import { Link } from 'react-router-dom';
4+
import useOnclickOutside from 'react-cool-onclickoutside';
5+
import { useCustomerData, useTranslation } from './app-state';
6+
import { LoginDialog } from './LoginDialog';
7+
import { ReactComponent as AccountIcon } from './images/icons/ic_account.svg';
8+
9+
import './AccountDropdown.scss';
10+
11+
export const AccountDropdown: React.FC = (props) => {
12+
const { isLoggedIn, customerEmail, customerName, clearCustomerData } = useCustomerData();
13+
const { t } = useTranslation();
14+
15+
const [isOpen, setIsOpen] = useState(false);
16+
const [isModalOpen, setIsModalOpen] = useState(false);
17+
18+
const handleSelectorClicked = () => {
19+
setIsOpen(true);
20+
};
21+
22+
const ref = useOnclickOutside(() => {
23+
setIsOpen(false);
24+
});
25+
26+
const logout = () => {
27+
clearCustomerData();
28+
};
29+
30+
if (isLoggedIn) {
31+
return (
32+
<div className="accountdropdown">
33+
<div className={`accountdropdown__dropdown ${isOpen ? 'accountdropdown__open' : ''}`}>
34+
<button className="accountdropdown__btn" type="button" aria-label="toggle profile menu" onClick={handleSelectorClicked}>
35+
<AccountIcon className="accountdropdown__btnicon" />
36+
</button>
37+
{isOpen && (
38+
<div className="accountdropdown__menu" ref={ref}>
39+
<ul className="accountdropdown__list">
40+
<li className="accountdropdown__listitem accountdropdown__itemtitle">
41+
<p className="accountdropdown__iteminfo">{customerName}</p>
42+
<p className="accountdropdown__iteminfo accountdropdown__emailinfo">{customerEmail}</p>
43+
</li>
44+
{/*<li className="accountdropdown__listitem">*/}
45+
{/* <Link to="/profile" className="accountdropdown__link">*/}
46+
{/* My Account*/}
47+
{/* </Link>*/}
48+
{/*</li>*/}
49+
<li className="accountdropdown__listitem accountdropdown__itembtns">
50+
<button className="epbtn --primary --fullwidth" type="button" onClick={logout}>
51+
{t('logout')}
52+
</button>
53+
</li>
54+
</ul>
55+
</div>
56+
)}
57+
</div>
58+
</div>
59+
);
60+
}
61+
62+
return (
63+
<div className="accountdropdown">
64+
<button className="accountdropdown__loginbtn" type="button" onClick={() => {setIsModalOpen(true)}}>
65+
{t('login')}
66+
</button>
67+
<LoginDialog openModal={isModalOpen} handleModalClose={() => {setIsModalOpen(false)}} />
68+
</div>
69+
);
70+
};

src/AppHeader.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
padding-left: 40px;
1111
}
1212

13+
&__account {
14+
margin-right: 20px;
15+
}
16+
1317
&__language {
1418
margin-right: 20px;
1519
}

src/AppHeader.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useTranslation } from './app-state';
55
import { LanguageDropdown } from './LanguageDropdown';
66

77
import './AppHeader.scss';
8+
import { AccountDropdown } from './AccountDropdown';
89
import headerLogo from './images/site-images/Company-Logo.svg';
910

1011

@@ -18,6 +19,9 @@ export const AppHeader: React.FC = () => {
1819
<ImageContainer imgUrl={headerLogo} imgClassName="logo-image" alt="logoImage"/>
1920
</Link>
2021
</div>
22+
<div className="appheader__account">
23+
<AccountDropdown />
24+
</div>
2125
<div className="appheader__language">
2226
<LanguageDropdown />
2327
</div>

src/LoginDialog.scss

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
2+
@import './theme/common.scss';
3+
4+
.logindialog {
5+
min-width: 500px;
6+
margin: auto;
7+
8+
&__header {
9+
display: flex;
10+
justify-content: space-between;
11+
align-items: center;
12+
padding: 5px 5px 10px;
13+
border-bottom: 1px solid $firstBorderColor;
14+
}
15+
16+
&__title {
17+
font-size: 15px;
18+
}
19+
20+
&__content {
21+
background-color: $mainBackgroundColor;
22+
border: none;
23+
24+
&.--loading {
25+
26+
&:before {
27+
content: '';
28+
height: 100%;
29+
width: 100%;
30+
position: absolute;
31+
top: 0;
32+
left: 0;
33+
background-color: $mainBackgroundColor;
34+
opacity: 0.5;
35+
z-index: 1;
36+
}
37+
}
38+
}
39+
40+
&__body {
41+
position: relative;
42+
padding: 25px 5px 5px;
43+
}
44+
45+
&__feedback {
46+
position: absolute;
47+
top: 0;
48+
left: 0;
49+
margin-top: 5px;
50+
font-weight: bold;
51+
color: $mainErrorColor;
52+
}
53+
54+
.epbtn + .epbtn {
55+
margin-left: 10px;
56+
}
57+
}
58+
59+
@media (max-width: $mobileWidth - 1) {
60+
.logindialog {
61+
height: 100%;
62+
min-width: 100%;
63+
}
64+
}

0 commit comments

Comments
 (0)