├── src ├── react-app-env.d.ts ├── assets │ ├── keleya-logo.png │ ├── yoga-1-033-copy.png │ ├── Balkon_smoothie_2773.jpeg │ └── balkon-smoothie-2773.png ├── GlobalStyles.ts ├── setupTests.ts ├── App.test.tsx ├── reportWebVitals.ts ├── components │ └── Button.tsx ├── index.tsx ├── utils │ └── i18n.ts ├── App.tsx ├── locales │ ├── en.json │ └── de.json └── pages │ ├── EmailSent.tsx │ ├── SuccessChange.tsx │ ├── ChooseNewPassword.tsx │ ├── ForgotPassword.tsx │ └── ChangePassword.tsx ├── public ├── robots.txt ├── favicon.ico ├── keleya-logo.png ├── manifest.json └── index.html ├── failed-screen.png ├── .prettierrc ├── cypress ├── tsconfig.json ├── fixtures │ └── example.json ├── integration │ └── screenshot-tests.spec.ts ├── snapshots │ └── screenshot-tests.spec.ts │ │ └── __diff_output__ │ │ └── screenshot tests -- navigate to forgot password page -- compares screenshots on this page.diff.png ├── support │ ├── index.ts │ └── commands.ts └── plugins │ └── index.ts ├── cypress.json ├── .gitignore ├── tsconfig.json ├── package.json └── README.md /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /failed-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/failed-screen.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } 6 | -------------------------------------------------------------------------------- /public/keleya-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/public/keleya-logo.png -------------------------------------------------------------------------------- /src/assets/keleya-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/src/assets/keleya-logo.png -------------------------------------------------------------------------------- /src/assets/yoga-1-033-copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/src/assets/yoga-1-033-copy.png -------------------------------------------------------------------------------- /src/assets/Balkon_smoothie_2773.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/src/assets/Balkon_smoothie_2773.jpeg -------------------------------------------------------------------------------- /src/assets/balkon-smoothie-2773.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/src/assets/balkon-smoothie-2773.png -------------------------------------------------------------------------------- /cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["es5", "dom"], 5 | "types": ["cypress", "node"] 6 | }, 7 | "include": ["**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultCommandTimeout": 10000, 3 | "pageLoadTimeout": 10000, 4 | "responseTimeout": 10000, 5 | "video": false, 6 | "baseUrl": "https://keleya.netlify.app/" 7 | } 8 | -------------------------------------------------------------------------------- /cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /src/GlobalStyles.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components'; 2 | 3 | export default createGlobalStyle` 4 | body { 5 | margin: 0; 6 | padding: 0; 7 | font-family: "Roboto", serif; 8 | } 9 | `; 10 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /cypress/integration/screenshot-tests.spec.ts: -------------------------------------------------------------------------------- 1 | describe('screenshot tests', () => { 2 | describe('navigate to forgot password page', () => { 3 | before(() => { 4 | cy.visit('/?lng=de'); 5 | cy.viewport(375, 812); 6 | }); 7 | it('compares screenshots on this page', () => { 8 | cy.matchImageSnapshot(); 9 | }); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /cypress/snapshots/screenshot-tests.spec.ts/__diff_output__/screenshot tests -- navigate to forgot password page -- compares screenshots on this page.diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ebazhanov/reset-password-flow/HEAD/cypress/snapshots/screenshot-tests.spec.ts/__diff_output__/screenshot tests -- navigate to forgot password page -- compares screenshots on this page.diff.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .idea 21 | /cypress/videos 22 | /cypress/screenshots 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | package-lock.json 28 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /src/components/Button.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Box, Typography } from '@material-ui/core/'; 3 | 4 | interface propTypes { 5 | onClick: (event: React.MouseEvent) => void; 6 | text: string; 7 | className: string; 8 | styles?: React.CSSProperties; 9 | } 10 | 11 | const Button: React.FC = (propTypes) => { 12 | return ( 13 | 14 | {propTypes.text} 15 | 16 | ); 17 | }; 18 | 19 | export default Button; 20 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "keleya-logo.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "keleya-logo.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import GlobalStyles from './GlobalStyles'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import './utils/i18n'; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | 12 | , 13 | document.getElementById('root') 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /src/utils/i18n.ts: -------------------------------------------------------------------------------- 1 | import i18next from 'i18next'; 2 | import { initReactI18next } from 'react-i18next'; 3 | import LanguageDetector from 'i18next-browser-languagedetector'; 4 | import de from '../locales/de.json'; 5 | import en from '../locales/en.json'; 6 | 7 | export const SupportedLocales = { 8 | de: { translation: de }, 9 | en: { translation: en }, 10 | }; 11 | 12 | export const i18n = i18next 13 | .use(initReactI18next) 14 | .use(LanguageDetector) 15 | .init({ 16 | resources: SupportedLocales, 17 | fallbackLng: 'de', 18 | debug: false, 19 | interpolation: { 20 | escapeValue: false, 21 | }, 22 | supportedLngs: ['en', 'de'], 23 | }); 24 | -------------------------------------------------------------------------------- /cypress/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /cypress/plugins/index.ts: -------------------------------------------------------------------------------- 1 | /// 2 | // *********************************************************** 3 | // This example plugins/index.js can be used to load plugins 4 | // 5 | // You can change the location of this file or turn off loading 6 | // the plugins file with the 'pluginsFile' configuration option. 7 | // 8 | // You can read more here: 9 | // https://on.cypress.io/plugins-guide 10 | // *********************************************************** 11 | 12 | // This function is called when a project is opened or re-opened (e.g. due to 13 | // the project's config changing) 14 | 15 | /** 16 | * @type {Cypress.PluginConfig} 17 | */ 18 | // eslint-disable-next-line no-unused-vars 19 | const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin'); 20 | 21 | module.exports = (on, config) => { 22 | addMatchImageSnapshotPlugin(on, config); 23 | }; 24 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { BrowserRouter, Route, Switch } from 'react-router-dom'; 3 | import EmailSent from './pages/EmailSent'; 4 | import ForgotPassword from './pages/ForgotPassword'; 5 | import ChangePassword from './pages/ChangePassword'; 6 | import ChooseNewPassword from './pages/ChooseNewPassword'; 7 | import SuccessChange from './pages/SuccessChange'; 8 | 9 | function App() { 10 | const [data, setData] = useState({}); 11 | 12 | useEffect(() => { 13 | setData(JSON.parse(localStorage.getItem('Data') || '{}')); 14 | }, []); 15 | 16 | return ( 17 | 18 | 19 | } /> 20 | 21 | 22 | } /> 23 | 24 | 25 | 26 | ); 27 | } 28 | 29 | export default App; 30 | -------------------------------------------------------------------------------- /cypress/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add('login', (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This will overwrite an existing command -- 25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) 26 | 27 | import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command'; 28 | 29 | addMatchImageSnapshotCommand({ 30 | failureThreshold: 0.00, // threshold for entire image 31 | failureThresholdType: 'percent', // percent of image or number of pixels 32 | customDiffConfig: { threshold: 0.1 }, // threshold for each pixel 33 | capture: 'viewport', // capture viewport in screenshot 34 | }); 35 | -------------------------------------------------------------------------------- /src/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "forgot_password_page": { 3 | "title": "Forgot your password?", 4 | "no_problem_give_your_email": " No problem, it happens! Just give us your email address and we'll send you a reset link.", 5 | "label": "E-mail address", 6 | "warning_message": "Please enter a valid email", 7 | "button": "Send me a reset link" 8 | }, 9 | "email_sent_page": { 10 | "title": "An email is on its way.", 11 | "message": "Click the link in your email to reset your password." 12 | }, 13 | "new_password_page": { 14 | "title": "Hi Jess! Forgot your password?", 15 | "body_message_one": "No problem it happens! If you click the link below you can pick a new one.", 16 | "body_message_two": "If you didn't request a password change please get in touch with us.", 17 | "button": "Choose new password" 18 | }, 19 | "change_password_page": { 20 | "title": "Reset your password", 21 | "message": "Choose a new one below", 22 | "new_password_label": "New password", 23 | "confirm_new_password_label": "Confirm new password", 24 | "button": "Save password", 25 | "warning_message": "Passwords don't match" 26 | }, 27 | "success_change_page": { 28 | "title": "Success!", 29 | "message": "Your password has been changed. We are looking forward to seeing you again soon.", 30 | "button": "Go to my profile" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/locales/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "forgot_password_page": { 3 | "title": "Du hast dein Passwort vergessen?", 4 | "no_problem_give_your_email": " Kein Problem, dass kann passieren! Gib unten einfach deine E-Mail Adresse ein und wir schicken dir einen Link zum Zurücksetzen.", 5 | "label": "E-Mail Adresse", 6 | "warning_message": "Please enter a valid email", 7 | "button": "Schick mir einen Link" 8 | }, 9 | "email_sent_page": { 10 | "title": "Eine E-mail ist unterwegs", 11 | "message": "Click auf den Link in deiner email, um dein Passwort zurückzusetzen." 12 | }, 13 | "new_password_page": { 14 | "title": "Hallo Jess! Du mochtest dein Passwort zurücksetzen?", 15 | "body_message_one": "Wir haben eine anfrage erhalten, dein Passwort zurückzusetzen.", 16 | "body_message_two": "Falls du diese Anfrage nicht verschickt hast, ignoriere diese E-Mail einfach. Um ein neues Passwort zu vergeben, kicke auf den Link und vergib eine neues Passwort.", 17 | "button": "Neues Passwort vergeben" 18 | }, 19 | "change_password_page": { 20 | "title": "Passwort erfolgreich geändert!", 21 | "message": "Kein problem, dass kann passieren! Vergib unten einfach ein Neues Passwort", 22 | "new_password_label": "Neues Passwort", 23 | "confirm_new_password_label": "Neues Passwort wiederholen", 24 | "button": "Passwort speichern", 25 | "warning_message": "Passwörter stimmen nicht überein" 26 | }, 27 | "success_change_page": { 28 | "title": "Password erfolgreich geändert!", 29 | "message": "Dein Passwort wurde geändert. Wir freuen uns auf ein baldiges Wiedersehen.", 30 | "button": "Geh auf mein Profil" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "keleya", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "PORT=3002 react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "react-scripts test", 9 | "cypress:run": "cypress run --browser chrome --headed" 10 | }, 11 | "dependencies": { 12 | "@testing-library/jest-dom": "^5.11.4", 13 | "@testing-library/react": "^11.1.0", 14 | "@testing-library/user-event": "^12.1.10", 15 | "@types/jest": "^26.0.15", 16 | "@types/node": "^12.0.0", 17 | "@types/react": "^17.0.0", 18 | "@types/react-dom": "^17.0.0", 19 | "react": "^17.0.2", 20 | "react-dom": "^17.0.2", 21 | "react-router-dom": "^5.2.0", 22 | "react-scripts": "^4.0.3", 23 | "typescript": "^4.1.2", 24 | "web-vitals": "^1.0.1" 25 | }, 26 | "devDependencies": { 27 | "@material-ui/core": "^4.12.2", 28 | "@material-ui/icons": "^4.11.2", 29 | "@types/cypress-image-snapshot": "^3.1.6", 30 | "@types/react-router-dom": "^5.1.8", 31 | "@types/styled-components": "^5.1.11", 32 | "cypress": "^8.0.0", 33 | "cypress-image-snapshot": "^4.0.1", 34 | "i18next": "^20.3.4", 35 | "i18next-browser-languagedetector": "^6.1.2", 36 | "i18next-http-backend": "^1.2.7", 37 | "prettier": "^2.3.2", 38 | "react-i18next": "^11.11.3", 39 | "styled-components": "^5.3.0" 40 | }, 41 | "eslintConfig": { 42 | "extends": [ 43 | "react-app", 44 | "react-app/jest" 45 | ] 46 | }, 47 | "browserslist": { 48 | "production": [ 49 | ">0.2%", 50 | "not dead", 51 | "not op_mini all" 52 | ], 53 | "development": [ 54 | "last 1 chrome version", 55 | "last 1 firefox version", 56 | "last 1 safari version" 57 | ] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Web App with RESET-PASSWORD flow 2 | > [React](https://reactjs.org/) and [Typescript](https://www.typescriptlang.org/) 3 | 4 | Screenshot 2021-07-09 at 15 49 32 5 | 6 | ---- 7 | ### What was done: 8 | - [x] implement responsive design (mobile first) [DEMO https://keleya.netlify.app/](https://keleya.netlify.app/) 9 | - [x] add translation EN/DE 10 | - [x] store email/password in localStorage 11 | - [x] E2E screenshot tests 12 | 13 | ### Want to change translation manually DE/EN? 14 | - http://localhost:3002/?lng=en 15 | - http://localhost:3002/?lng=de 16 | 17 | ### Reset password flow 18 | - `$ yarn start` 19 | - Forgot password page [http://localhost:3002/](http://localhost:3002/) 20 | - Email sent page [http://localhost:3002/email-sent](https://keleya.netlify.app/email-sent) 21 | - Choose New Password page [http://localhost:3002/choose-new-password](http://localhost:3002/choose-new-password) 22 | - Change Password page [http://localhost:3002/change-password](http://localhost:3002/change-password) 23 | - Success page [http://localhost:3002/success](http://localhost:3002/success) 24 | 25 | ----- 26 | 27 | ### How to run screenshot comparison E2E tests: 28 | 29 | ![screenshot](failed-screen.png) 30 | 31 | - `$ yarn cypress:run` 32 | - find failed screen into `__diff_output__` folder: 33 | ``` 34 | Cypress 35 | ├── integration 36 | │ ├── screenshot-tests.spec.ts 37 | │ ├── snapshots 38 | │ │ └── screenshot-tests.spec.ts 39 | │ │ ├── __diff_output__ 40 | │ │ │ └── ... navigate to forgot password page.snap.png 41 | │ │ └── ... forgot password page.snap.png 42 | ``` 43 | - more info here [cypress-image-snapshot](https://github.com/jaredpalmer/cypress-image-snapshot) npm library 44 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Keleya 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/pages/EmailSent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles, Theme } from '@material-ui/core/styles'; 3 | import { Box, Container, Typography } from '@material-ui/core/'; 4 | import Logo from '../assets/keleya-logo.png'; 5 | import CloseIcon from '@material-ui/icons/Close'; 6 | import { useHistory } from 'react-router-dom'; 7 | import { useTranslation } from 'react-i18next'; 8 | 9 | const useStyles = makeStyles((theme: Theme) => ({ 10 | pageContainer: { 11 | maxWidth: '100%', 12 | maxHeight: '100vh', 13 | display: 'flex', 14 | flexDirection: 'column', 15 | alignItems: 'center', 16 | }, 17 | imageContainer: { 18 | marginTop: theme.spacing(15), 19 | height: 'calc(100vh - 70%)', 20 | justifyContent: 'center', 21 | textAlign: 'center', 22 | }, 23 | image: { 24 | width: '30%', 25 | }, 26 | title: { 27 | marginTop: theme.spacing(5), 28 | textAlignLast: 'center', 29 | }, 30 | textBody: { 31 | color: '#9b9b9b', 32 | marginTop: theme.spacing(3), 33 | }, 34 | closeIcon: { 35 | marginTop: theme.spacing(3), 36 | marginRight: theme.spacing(2), 37 | cursor: 'pointer', 38 | height: 'calc(100vh - 90%)', 39 | alignSelf: 'flex-end', 40 | }, 41 | })); 42 | 43 | const EmailSent = () => { 44 | const classes = useStyles(); 45 | const history = useHistory(); 46 | const { t } = useTranslation(); 47 | const handleClick = () => history.push('/choose-new-password'); 48 | 49 | return ( 50 | 51 | 52 | 53 | logo 54 | 55 | 56 | 57 | {t('email_sent_page.title')} 58 | 59 | 60 | {t('email_sent_page.message')} 61 | 62 | 63 | 64 | ); 65 | }; 66 | 67 | export default EmailSent; 68 | -------------------------------------------------------------------------------- /src/pages/SuccessChange.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles, Theme } from '@material-ui/core/styles'; 3 | import { Box, Hidden, Typography } from '@material-ui/core/'; 4 | import Image from '../assets/yoga-1-033-copy.png'; 5 | import Logo from '../assets/keleya-logo.png'; 6 | import Button from '../../src/components/Button'; 7 | import { useHistory } from 'react-router-dom'; 8 | import { useTranslation } from 'react-i18next'; 9 | 10 | const useStyles = makeStyles((theme: Theme) => ({ 11 | pageContainer: { 12 | backgroundImage: `url(${Image})`, 13 | maxWidth: '100%', 14 | height: '100vh', 15 | backgroundPosition: 'center', 16 | backgroundSize: 'cover', 17 | backgroundRepeat: 'no-repeat', 18 | display: 'flex', 19 | }, 20 | content: { 21 | boxSizing: 'border-box', 22 | paddingTop: theme.spacing(6), 23 | height: '60%', 24 | width: '100%', 25 | background: 'rgba(255, 255, 255, .8)', 26 | display: 'flex', 27 | justifyContent: 'center', 28 | alignSelf: 'flex-end', 29 | }, 30 | contentWrapper: { 31 | width: '100%', 32 | maxWidth: '490px', 33 | padding: '0 20px', 34 | display: 'flex', 35 | flexDirection: 'column', 36 | }, 37 | title: { 38 | marginTop: theme.spacing(3), 39 | }, 40 | text: { 41 | color: '#9b9b9b', 42 | marginTop: theme.spacing(4), 43 | }, 44 | image: { 45 | width: '25%', 46 | marginTop: theme.spacing(13), 47 | alignSelf: 'center', 48 | }, 49 | buttonContainer: { 50 | background: '#9adcd7', 51 | color: '#ffffff', 52 | cursor: 'pointer', 53 | textAlign: 'center', 54 | marginTop: theme.spacing(4), 55 | 56 | [theme.breakpoints.down('xs')]: { 57 | marginTop: 'auto', 58 | margin: '0 -20px', 59 | width: 'calc(100% + 40px)', 60 | }, 61 | }, 62 | })); 63 | 64 | const SuccessChange = () => { 65 | const classes = useStyles(); 66 | const history = useHistory(); 67 | const { t } = useTranslation(); 68 | const handleClick = () => history.push('/'); 69 | 70 | return ( 71 | 72 | 73 | 74 |
75 | 76 | {t('success_change_page.title')} 77 | 78 | 79 | {t('success_change_page.message')} 80 | 81 |
82 | 83 | logo 84 | 85 | 86 |