diff --git a/frontend/package.json b/frontend/package.json index 07853ca3..e7690c85 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -3,6 +3,9 @@ "version": "3.0.0", "private": true, "dependencies": { + "@chakra-ui/react": "^1.6.12", + "@emotion/react": "^11", + "@emotion/styled": "^11", "@testing-library/jest-dom": "5.14.1", "@testing-library/react": "12.0.0", "@types/humps": "^2.0.0", @@ -28,6 +31,7 @@ "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-react": "^7.24.0", "eslint-plugin-react-hooks": "^4.2.0", + "framer-motion": "^4", "humps": "^2.0.1", "jest-date-mock": "1.0.8", "jest-fetch-mock": "3.0.3", diff --git a/frontend/public/index.html b/frontend/public/index.html index 3199d60e..c25a4ff8 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -47,14 +47,6 @@ content="/images/favicon/browserconfig.xml" /> - - - - - - - + + + + + + + ); diff --git a/frontend/src/components/LocalePicker.tsx b/frontend/src/components/LocalePicker.tsx index d079b19d..0f705af6 100644 --- a/frontend/src/components/LocalePicker.tsx +++ b/frontend/src/components/LocalePicker.tsx @@ -1,82 +1,71 @@ -import React, { useEffect, useRef, useState } from "react"; +import React from "react"; -import { Button, Dropdown, Flag } from "components"; +import { + Button, + Box, + Menu, + MenuButton, + MenuList, + MenuItem, +} from "@chakra-ui/react"; +import { Flag } from "components"; import { useLocaleState } from "context"; import { changeLocale, getFlagCodeForLocale, intl } from "locale"; export interface LocalPickerProps { /** - * On click handler + * On change handler */ onChange?: any; + /** + * Class + */ + className?: string; } export const LocalePicker: React.FC = ({ onChange, - ...rest + className, }) => { - const dropRef = useRef(null); const { locale, setLocale } = useLocaleState(); - const [localeShown, setLocaleShown] = useState(false); const options = [ ["us", "en-US"], ["de", "de-DE"], - ["ir", "fa-IR"], + ["fa", "fa-IR"], ]; - const handleOnChange = (e: any) => { - changeLocale(e.currentTarget.rel); - setLocale(e.currentTarget.rel); - setLocaleShown(false); + const changeTo = (lang: string) => { + changeLocale(lang); + setLocale(lang); onChange && onChange(locale); }; - const handleClickOutside = (event: any) => { - if ( - dropRef.current && - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - !dropRef.current.contains(event.target) - ) { - setLocaleShown(false); - } - }; - - useEffect(() => { - document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, []); - return ( - - { - setLocaleShown(!localeShown); - e.preventDefault(); - }} - iconOnly> - - - - {options.map((item) => { - return ( - } - onClick={handleOnChange}> - {intl.formatMessage({ - id: `locale-${item[1]}`, - defaultMessage: item[1], - })} - - ); - })} - - + + + + + + + {options.map((item) => { + return ( + } + onClick={() => changeTo(item[0])} + rel={item[1]} + key={`locale-${item[0]}`}> + + {intl.formatMessage({ + id: `locale-${item[1]}`, + defaultMessage: item[1], + })} + + + ); + })} + + + ); }; diff --git a/frontend/src/img/logo-256.png b/frontend/src/img/logo-256.png new file mode 100644 index 00000000..2bfb661d Binary files /dev/null and b/frontend/src/img/logo-256.png differ diff --git a/frontend/src/index.scss b/frontend/src/index.scss index cccad46f..8a3e6b8e 100644 --- a/frontend/src/index.scss +++ b/frontend/src/index.scss @@ -17,59 +17,3 @@ body { .text-right { text-align: right; } - -// Hide the dropdown arrow when it is inlined in the mobile menu -@media (max-width: 767.98px) { - .navbar-collapse .dropdown-menu-arrow::before { - display: none; - } -} - -/* -.btn { - text-transform: none; -} - -.btn-loading { - color: transparent !important; - pointer-events: none; - position: relative; - - &:after { - content: ""; - -webkit-animation: loader 500ms infinite linear; - animation: loader 500ms infinite linear; - border: 2px solid #fff; - border-radius: 50%; - border-right-color: transparent !important; - border-top-color: transparent !important; - display: block; - height: 1.4em; - width: 1.4em; - position: absolute; - left: calc(50% - (1.4em / 2)); - top: calc(50% - (1.4em / 2)); - -webkit-transform-origin: center; - transform-origin: center; - position: absolute !important; - } -} - -.footer { - background: #fff; - border-top: 1px solid rgba(0, 40, 100, 0.12); - font-size: 0.875rem; - padding: 1.25rem 0; - color: #9aa0ac; - - a:not(.btn) { - color: #6e7687; - text-decoration: none; - background-color: initial; - - &:hover { - text-decoration: underline; - } - } -} -*/ diff --git a/frontend/src/pages/Login/index.tsx b/frontend/src/pages/Login/index.tsx index e33dda03..e86077ca 100644 --- a/frontend/src/pages/Login/index.tsx +++ b/frontend/src/pages/Login/index.tsx @@ -1,17 +1,27 @@ import React, { useEffect, useRef, useState, ChangeEvent } from "react"; -import { Alert, Button } from "components"; +import { + Flex, + Box, + FormControl, + FormLabel, + Input, + Stack, + Button, + useColorModeValue, + useToast, +} from "@chakra-ui/react"; import { LocalePicker } from "components"; import { useAuthState } from "context"; import { intl } from "locale"; -import logo from "../../img/logo-text-vertical-grey.png"; +import logo from "../../img/logo-256.png"; function Login() { + const toast = useToast(); const emailRef = useRef(null); const { login } = useAuthState(); const [loading, setLoading] = useState(false); - const [errorMessage, setErrorMessage] = useState(""); const [formData, setFormData] = useState({ email: "", password: "", @@ -20,12 +30,18 @@ function Login() { const onSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); - setErrorMessage(""); try { await login(formData.email, formData.password); } catch (err: any) { - setErrorMessage(err.message); + toast({ + title: "Login Error", + description: err.message, + status: "error", + position: "top", + duration: 3000, + isClosable: true, + }); setLoading(false); } }; @@ -40,87 +56,92 @@ function Login() { }, []); return ( - - - - - - - - - - - - - {errorMessage ? {errorMessage} : null} - - - {intl.formatMessage({ - id: "user.email", - defaultMessage: "Email", - })} - - - - - - {intl.formatMessage({ - id: "user.password", - defaultMessage: "Password", - })} - - - - - - - - {intl.formatMessage({ - id: "login.login", - defaultMessage: "Sign in", - })} - - - - - + + + + + + + + + + + + {intl.formatMessage({ + id: "user.email", + defaultMessage: "Email", + })} + + + + + + {intl.formatMessage({ + id: "user.password", + defaultMessage: "Password", + })} + + + + + + + {intl.formatMessage({ + id: "login.login", + defaultMessage: "Sign in", + })} + + + + + + + ); }