| @@ -0,0 +1,3 @@ | |||||
| <svg xmlns="http://www.w3.org/2000/svg" width="13" height="22.609" viewBox="0 0 13 22.609"> | |||||
| <path id="back-light" d="M19.857,21.952,9.9,12.162l9.953-9.79L18.319.857,6.857,12.168l11.462,11.3Z" transform="translate(-6.857 -0.857)" fill-rule="evenodd"/> | |||||
| </svg> | |||||
| @@ -1,3 +1,3 @@ | |||||
| <svg xmlns="http://www.w3.org/2000/svg" width="19.34" height="19.221" viewBox="0 0 19.34 19.221"> | <svg xmlns="http://www.w3.org/2000/svg" width="19.34" height="19.221" viewBox="0 0 19.34 19.221"> | ||||
| <path id="speaker" d="M0,5.7H4.558L11.414.111V19.332L4.558,13.744H0Zm13.99-.912A6.83,6.83,0,0,1,16.05,9.7a6.364,6.364,0,0,1-2.061,4.755L12.6,13.03a4.607,4.607,0,0,0,1.427-3.369A4.783,4.783,0,0,0,12.6,6.213L13.99,4.786Zm2.378-2.338A9.774,9.774,0,0,1,19.34,9.622a9.9,9.9,0,0,1-2.972,7.213L14.9,15.369a7.722,7.722,0,0,0,2.378-5.727A7.852,7.852,0,0,0,14.9,3.876l1.467-1.427Z" transform="translate(0 -0.111)" fill="#fff"/> | |||||
| <path id="speaker" d="M0,5.7H4.558L11.414.111V19.332L4.558,13.744H0Zm13.99-.912A6.83,6.83,0,0,1,16.05,9.7a6.364,6.364,0,0,1-2.061,4.755L12.6,13.03a4.607,4.607,0,0,0,1.427-3.369A4.783,4.783,0,0,0,12.6,6.213L13.99,4.786Zm2.378-2.338A9.774,9.774,0,0,1,19.34,9.622a9.9,9.9,0,0,1-2.972,7.213L14.9,15.369a7.722,7.722,0,0,0,2.378-5.727A7.852,7.852,0,0,0,14.9,3.876l1.467-1.427Z" transform="translate(0 -0.111)"/> | |||||
| </svg> | </svg> | ||||
| @@ -0,0 +1,224 @@ | |||||
| .modalPage { | |||||
| background-color: var(--creamy-white); | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| z-index: 2; | |||||
| width: 100vw; | |||||
| height: 100vh; | |||||
| overflow: auto; | |||||
| opacity: 0; | |||||
| animation: fadeIn 0.3s forwards; | |||||
| @keyframes fadeIn { | |||||
| 0% { | |||||
| opacity: 0; | |||||
| transform: translateY(10vh); | |||||
| } 100% { | |||||
| opacity: 1; | |||||
| transform: translateY(0vh); | |||||
| } | |||||
| } | |||||
| } | |||||
| .navHeader { | |||||
| background-color: transparent; | |||||
| text-align: center; | |||||
| position: relative; | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| padding: 1rem 1.5rem; | |||||
| button { | |||||
| width: 4rem; | |||||
| text-align: center; | |||||
| background-color: transparent; | |||||
| border: 0; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: flex-start; | |||||
| svg { | |||||
| width: 1rem; | |||||
| color: var(--black); | |||||
| } | |||||
| } | |||||
| h5 { | |||||
| font-size: 1.5rem; | |||||
| } | |||||
| figure { | |||||
| display: block; | |||||
| img { | |||||
| display: block; | |||||
| width: 4rem; | |||||
| height: 4rem; | |||||
| border-radius: 50%; | |||||
| border: 1px solid var(--creamy-white); | |||||
| } | |||||
| } | |||||
| } | |||||
| .searchBarHolder { | |||||
| background-color: var(--teal); | |||||
| padding: 2rem 0 6rem; | |||||
| border-top-right-radius: 3rem; | |||||
| border-top-left-radius: 3rem; | |||||
| .searchBar { | |||||
| background-color: white; | |||||
| display: flex; | |||||
| border-radius: 3rem; | |||||
| height: 5rem; | |||||
| width: calc(100% - 6rem); | |||||
| margin: 0 auto; | |||||
| align-items: center; | |||||
| justify-content: space-between; | |||||
| box-shadow: 0px 5px 30px -20px var(--grey); | |||||
| input { | |||||
| height: 100%; | |||||
| border: 0; | |||||
| width: calc(100% - 5rem); | |||||
| background-color: transparent; | |||||
| padding-left: 2rem; | |||||
| font-size: 1.4rem; | |||||
| } | |||||
| svg { | |||||
| width: 5rem; | |||||
| fill: var(--red); | |||||
| } | |||||
| } | |||||
| } | |||||
| .searchResult { | |||||
| background-color: var(--creamy-white); | |||||
| border-top-right-radius: 3rem; | |||||
| border-top-left-radius: 3rem; | |||||
| margin: -4rem 0; | |||||
| min-height: 5rem; | |||||
| padding: 2rem; | |||||
| li { | |||||
| position: relative; | |||||
| overflow: hidden; | |||||
| border-radius: 2rem; | |||||
| padding: 1rem 1.5rem; | |||||
| margin-bottom: 1.5rem; | |||||
| &:nth-child(2n) { | |||||
| &::before { | |||||
| background-color: var(--teal); | |||||
| } | |||||
| header { | |||||
| h4 { | |||||
| span { | |||||
| color: var(--teal); | |||||
| } | |||||
| } | |||||
| } | |||||
| .description { | |||||
| span, p { | |||||
| color: var(--teal); | |||||
| } | |||||
| } | |||||
| } | |||||
| &::before { | |||||
| content: ''; | |||||
| position: absolute; | |||||
| left: 0; | |||||
| top: 0; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| background-color: var(--orange); | |||||
| opacity: 0.3; | |||||
| } | |||||
| &>* { | |||||
| position: relative; | |||||
| } | |||||
| header { | |||||
| display: flex; | |||||
| align-items: flex-start; | |||||
| justify-content: space-between; | |||||
| h4 { | |||||
| font-size: 2rem; | |||||
| font-weight: 600; | |||||
| color: var(--black); | |||||
| span { | |||||
| display: block; | |||||
| font-size: 1.2rem; | |||||
| color: var(--orange); | |||||
| filter: brightness(50%); | |||||
| font-weight: 500; | |||||
| } | |||||
| } | |||||
| button { | |||||
| background-color: transparent; | |||||
| border: none; | |||||
| background-color: var(--orange); | |||||
| width: 4rem; | |||||
| height: 4rem; | |||||
| border-radius: 50%; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| svg { | |||||
| width: 1.7rem; | |||||
| fill: white; | |||||
| } | |||||
| } | |||||
| } | |||||
| .description { | |||||
| margin: 1rem 0; | |||||
| filter: brightness(40%); | |||||
| opacity: 0.7; | |||||
| span { | |||||
| font-size: 1.2rem; | |||||
| color: var(--orange); | |||||
| font-weight: 600; | |||||
| text-transform: lowercase; | |||||
| } | |||||
| p { | |||||
| font-size: 1.2rem; | |||||
| color: var(--orange); | |||||
| } | |||||
| } | |||||
| .addButton { | |||||
| width: 7rem; | |||||
| margin-left: auto; | |||||
| border: none; | |||||
| border-radius: 3rem; | |||||
| height: 3rem; | |||||
| cursor: pointer; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| font-size: 1.2rem; | |||||
| color: white; | |||||
| background-color: var(--orange); | |||||
| svg { | |||||
| fill: white; | |||||
| width: 1rem; | |||||
| margin-right: 0.5rem; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,68 @@ | |||||
| import React, { useState } from "react"; | |||||
| import styles from './AddWord.module.scss'; | |||||
| import { ReactComponent as ChevronLeft } from '../../assets/icons/chevron-left.svg'; | |||||
| import { ReactComponent as SearchIcon } from '../../assets/icons/bx-search-alt.svg'; | |||||
| import { ReactComponent as SpeakerIcon } from '../../assets/icons/speaker.svg'; | |||||
| import { ReactComponent as AddIcon } from '../../assets/icons/plus.svg'; | |||||
| import { IWord } from "../../structure/word"; | |||||
| import { ALL_WORDS } from "../../data/all-words"; | |||||
| type OwnProps = { | |||||
| hideModal: () => void; | |||||
| }; | |||||
| export const AddWord: React.FC<OwnProps> = (props: OwnProps) => { | |||||
| const [searchResult, setSearchResult] = useState<Array<IWord>>([]); | |||||
| const searchWords = (searchWord: string) => { | |||||
| if (searchWord.length > 0) { | |||||
| let result = ALL_WORDS.filter((word) => { | |||||
| return word.name.toLowerCase().includes(searchWord.toLowerCase()); | |||||
| }); | |||||
| setSearchResult(result); | |||||
| } else { | |||||
| setSearchResult([]); | |||||
| } | |||||
| } | |||||
| return <section className={styles.modalPage}> | |||||
| <header className={styles.navHeader}> | |||||
| <button onClick={props.hideModal}> | |||||
| <ChevronLeft /> | |||||
| </button> | |||||
| <h5> Add a Word </h5> | |||||
| <figure> | |||||
| {/* eslint-disable-next-line */} | |||||
| <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSERA5Pm3aRBV7AaI8tvpZfzpD24ZgrU1_8NA&usqp=CAU" alt="profile-image" /> | |||||
| </figure> | |||||
| </header> | |||||
| <div className={styles.searchBarHolder}> | |||||
| <div className={styles.searchBar}> | |||||
| <input type="text" autoFocus={true} placeholder={'Search and add a word'} onChange={(event) => searchWords(event.currentTarget.value)} /> | |||||
| <SearchIcon /> | |||||
| </div> | |||||
| </div> | |||||
| <ul className={styles.searchResult}> | |||||
| { searchResult.map((word) => { | |||||
| return <li key={word.name}> | |||||
| <header> | |||||
| <h4> { word.name } <span> { word.pronounciation } </span> </h4> | |||||
| <button> | |||||
| <SpeakerIcon /> | |||||
| </button> | |||||
| </header> | |||||
| <div className={styles.description}> | |||||
| <span> { word.grammaticalDetails[0].typeName } </span> | |||||
| <p> { word.grammaticalDetails[0].description } </p> | |||||
| </div> | |||||
| <button className={styles.addButton}> <AddIcon /> Add </button> | |||||
| </li> | |||||
| }) } | |||||
| </ul> | |||||
| </section> | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| import React from "react"; | |||||
| import React, { useState } from "react"; | |||||
| import styles from './Home.module.scss'; | import styles from './Home.module.scss'; | ||||
| import { ReactComponent as LogoIcon } from '../../assets/icons/anamnesis.svg'; | import { ReactComponent as LogoIcon } from '../../assets/icons/anamnesis.svg'; | ||||
| import { ReactComponent as SearchIcon } from '../../assets/icons/bx-search-alt.svg'; | import { ReactComponent as SearchIcon } from '../../assets/icons/bx-search-alt.svg'; | ||||
| @@ -15,11 +15,13 @@ import { ReactComponent as GridIcon } from '../../assets/icons/circled.svg'; | |||||
| import { ReactComponent as PersonSpeakerIcon } from '../../assets/icons/user-speaker.svg'; | import { ReactComponent as PersonSpeakerIcon } from '../../assets/icons/user-speaker.svg'; | ||||
| import { ReactComponent as BrainIcon } from '../../assets/icons/bx-brain.svg'; | import { ReactComponent as BrainIcon } from '../../assets/icons/bx-brain.svg'; | ||||
| import { ReactComponent as InternBadge } from '../../assets/icons/intern-badge.svg'; | import { ReactComponent as InternBadge } from '../../assets/icons/intern-badge.svg'; | ||||
| import { CircularProgressbar } from 'react-circular-progressbar'; | import { CircularProgressbar } from 'react-circular-progressbar'; | ||||
| import { AddWord } from "../add-word/AddWord"; | |||||
| export const Home: React.FC = () => { | export const Home: React.FC = () => { | ||||
| const [isAddWordModalOpen, setAddWordModalState] = useState<boolean>(false); | |||||
| return <section className="page"> | return <section className="page"> | ||||
| <header className={styles.pageHeader}> | <header className={styles.pageHeader}> | ||||
| @@ -57,7 +59,7 @@ export const Home: React.FC = () => { | |||||
| </section> | </section> | ||||
| <div className={styles.searchBar}> | <div className={styles.searchBar}> | ||||
| <input type="text" placeholder={'Search and add a word'} /> | |||||
| <input type="text" placeholder={'Search and add a word'} onClick={() => setAddWordModalState(true)} /> | |||||
| <SearchIcon /> | <SearchIcon /> | ||||
| </div> | </div> | ||||
| @@ -252,5 +254,8 @@ export const Home: React.FC = () => { | |||||
| </ul> | </ul> | ||||
| </section> | </section> | ||||
| { isAddWordModalOpen && <AddWord hideModal={() => { setAddWordModalState(false); }} /> } | |||||
| </section> | </section> | ||||
| } | } | ||||
| @@ -9,7 +9,7 @@ import { ReactComponent as MoreIcon } from '../../assets/icons/more-vertical.svg | |||||
| import { NavLink } from "react-router-dom"; | import { NavLink } from "react-router-dom"; | ||||
| export const Tabs: React.FC = () => { | export const Tabs: React.FC = () => { | ||||
| return <section className={styles.tabs} id="tabs"> | |||||
| return <section className={styles.tabs}> | |||||
| <NavLink to={'/home'} activeClassName={styles.active}> | <NavLink to={'/home'} activeClassName={styles.active}> | ||||
| <HomeIcon /> | <HomeIcon /> | ||||
| </NavLink > | </NavLink > | ||||
| @@ -0,0 +1,27 @@ | |||||
| import { IWord } from "../structure/word"; | |||||
| export const ALL_WORDS: Array<IWord> = [{ | |||||
| name: 'Pleasure', | |||||
| pronounciation: '/ˈplɛʒə/', | |||||
| audioPronounciationURL: '', | |||||
| grammaticalDetails: [{ | |||||
| typeName: 'NOUN', | |||||
| description: 'a feeling of happy satisfaction and enjoyment.' | |||||
| }, { | |||||
| typeName: 'ADJECTIVE', | |||||
| description: 'used or intended for entertainment rather than business.' | |||||
| }], | |||||
| similarWords: ['Happiness', 'Delight', 'Joy', 'Rapture', 'Glee'], | |||||
| }, { | |||||
| name: 'Please', | |||||
| pronounciation: '/pliːz/', | |||||
| audioPronounciationURL: '', | |||||
| grammaticalDetails: [{ | |||||
| typeName: 'VERB', | |||||
| description: 'cause to feel happy and satisfied.' | |||||
| }, { | |||||
| typeName: 'ADVERB', | |||||
| description: 'used in polite requests or questions.' | |||||
| }], | |||||
| similarWords: ['Nice', 'Agreeable', 'Pleasant', 'Satisfying', 'Gratifying'], | |||||
| }] | |||||
| @@ -3,7 +3,7 @@ export type IWord = { | |||||
| pronounciation: string, | pronounciation: string, | ||||
| audioPronounciationURL: string, | audioPronounciationURL: string, | ||||
| grammaticalDetails: Array<{ | grammaticalDetails: Array<{ | ||||
| typeName: 'NOUN' | 'ADJECTIVE' | 'VERB', | |||||
| typeName: 'NOUN' | 'ADJECTIVE' | 'VERB' | 'ADVERB', | |||||
| description: string, | description: string, | ||||
| }>, | }>, | ||||
| similarWords: Array<string> | similarWords: Array<string> | ||||