@@ -107,8 +107,9 @@ | |||
position: relative; | |||
overflow: hidden; | |||
border-radius: 2rem; | |||
padding: 1rem 1.5rem; | |||
padding: 1rem 1.5rem 1.7rem; | |||
margin-bottom: 1.5rem; | |||
background-color: white; | |||
&:nth-child(2n) { | |||
&::before { | |||
@@ -121,6 +122,10 @@ | |||
color: var(--teal); | |||
} | |||
} | |||
button { | |||
background-color: var(--teal); | |||
} | |||
} | |||
.description { | |||
@@ -128,6 +133,10 @@ | |||
color: var(--teal); | |||
} | |||
} | |||
.addButton { | |||
background-color: var(--teal); | |||
} | |||
} | |||
&::before { | |||
@@ -138,7 +147,7 @@ | |||
width: 100%; | |||
height: 100%; | |||
background-color: var(--orange); | |||
opacity: 0.3; | |||
opacity: 0.4; | |||
} | |||
&>* { | |||
@@ -205,7 +214,7 @@ | |||
margin-left: auto; | |||
border: none; | |||
border-radius: 3rem; | |||
height: 3rem; | |||
height: 2.7rem; | |||
cursor: pointer; | |||
display: flex; | |||
align-items: center; | |||
@@ -221,4 +230,103 @@ | |||
} | |||
} | |||
} | |||
} | |||
.shelfList { | |||
list-style: none; | |||
padding: 1rem 2rem; | |||
header { | |||
margin: 0 auto 1rem; | |||
h5 { | |||
font-weight: 300; | |||
font-size: 1.2rem; | |||
color: var(--black); | |||
} | |||
} | |||
li { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
margin: 0 0 2rem; | |||
&:nth-child(3n) .icon { | |||
background-color: var(--red); | |||
} | |||
&:nth-child(3n - 1) .icon { | |||
background-color: var(--orange); | |||
} | |||
&:nth-child(3n - 2) .icon { | |||
background-color: var(--blue); | |||
} | |||
} | |||
.icon { | |||
width: 4rem; | |||
height: 4rem; | |||
background-color: var(--grey); | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
border-radius: 50%; | |||
svg { | |||
fill: white; | |||
width: 3rem; | |||
} | |||
} | |||
.info { | |||
width: calc(100% - 5rem); | |||
label, span { | |||
display: block; | |||
} | |||
label { | |||
font-size: 1.2rem; | |||
color: var(--black); | |||
font-weight: 700; | |||
} | |||
span { | |||
font-size: 1rem; | |||
color: var(--grey); | |||
} | |||
} | |||
} | |||
.AddShelfButton { | |||
position: fixed; | |||
bottom: 0; | |||
left: 0; | |||
padding: 2rem 3rem; | |||
display: flex; | |||
align-items: center; | |||
justify-content: flex-start; | |||
width: 100%; | |||
background-color: var(--creamy-white); | |||
border: none; | |||
box-shadow: 0px 0px 5px var(--creamy-white); | |||
font-weight: 600; | |||
color: var(--black); | |||
span { | |||
width: 3rem; | |||
height: 3rem; | |||
background-color: var(--teal); | |||
border-radius: 50%; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
margin-right: 1.5rem; | |||
svg { | |||
fill: white; | |||
width: 1.2rem; | |||
} | |||
} | |||
} |
@@ -7,13 +7,16 @@ import { ReactComponent as AddIcon } from '../../assets/icons/plus.svg'; | |||
import { IWord } from "../../structure/word"; | |||
import { ALL_WORDS } from "../../data/all-words"; | |||
import { userProfileData } from "../home/Home"; | |||
type OwnProps = { | |||
hideModal: () => void; | |||
hideModal: () => void | |||
}; | |||
export const AddWord: React.FC<OwnProps> = (props: OwnProps) => { | |||
const [searchResult, setSearchResult] = useState<Array<IWord>>([]); | |||
const [selectedWord, setSelectedWord] = useState<IWord>(); | |||
const searchWords = (searchWord: string) => { | |||
if (searchWord.length > 0) { | |||
@@ -48,7 +51,7 @@ export const AddWord: React.FC<OwnProps> = (props: OwnProps) => { | |||
</div> | |||
<ul className={styles.searchResult}> | |||
{ searchResult.map((word) => { | |||
{ !selectedWord && searchResult.map((word) => { | |||
return <li key={word.name}> | |||
<header> | |||
<h4> { word.name } <span> { word.pronounciation } </span> </h4> | |||
@@ -60,9 +63,32 @@ export const AddWord: React.FC<OwnProps> = (props: OwnProps) => { | |||
<span> { word.grammaticalDetails[0].typeName } </span> | |||
<p> { word.grammaticalDetails[0].description } </p> | |||
</div> | |||
<button className={styles.addButton}> <AddIcon /> Add </button> | |||
<button className={styles.addButton} onClick={() => setSelectedWord(word)}> <AddIcon /> Add </button> | |||
</li> | |||
}) } | |||
</ul> | |||
{ selectedWord && <ul className={styles.shelfList}> | |||
<header> | |||
<h5> All Shelves </h5> | |||
</header> | |||
{ userProfileData.categories.map((category, categoryIndex) => { | |||
return category.shelves.map((shelf, shelfIndex) => { | |||
return <li key={shelf.name} onClick={() => { | |||
userProfileData.categories[categoryIndex].shelves[shelfIndex].words.push(selectedWord); | |||
}}> | |||
<div className={styles.icon}> | |||
{ category.icon } | |||
</div> | |||
<div className={styles.info}> | |||
<label> { shelf.name } </label> | |||
<span> { category.name } </span> | |||
</div> | |||
</li> | |||
}) | |||
}) } | |||
<button className={styles.AddShelfButton}> <span> <AddIcon /> </span> Create New Shelf </button> | |||
</ul> } | |||
</section> | |||
} |
@@ -17,11 +17,52 @@ import { ReactComponent as BrainIcon } from '../../assets/icons/bx-brain.svg'; | |||
import { ReactComponent as InternBadge } from '../../assets/icons/intern-badge.svg'; | |||
import { CircularProgressbar } from 'react-circular-progressbar'; | |||
import { AddWord } from "../add-word/AddWord"; | |||
import { IProfile } from "../../structure/profile"; | |||
export var userProfileData : IProfile = { | |||
name: 'Neymar Jr', | |||
image: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSERA5Pm3aRBV7AaI8tvpZfzpD24ZgrU1_8NA&usqp=CAU', | |||
medal: { | |||
name: 'Intern badge', | |||
minValue: 0, | |||
maxValue: 100, | |||
icon: <InternBadge /> | |||
}, | |||
categories: [{ | |||
name: 'Vocabulary', | |||
icon: <TimeIcon />, | |||
shelves: [{ | |||
name: 'All Words', | |||
words: [], | |||
revisedWords: [], | |||
description: 'All Words that I use on a daily basis', | |||
viewPermission: 'PUBLIC' | |||
}] | |||
}, { | |||
name: 'Books', | |||
icon: <BookMarkIcon />, | |||
shelves: [{ | |||
name: 'Sapiens', | |||
words: [], | |||
revisedWords: [], | |||
description: 'Sapiens book complex words', | |||
viewPermission: 'PUBLIC' | |||
}] | |||
}, { | |||
name: 'GRE', | |||
icon: <BrainIcon />, | |||
shelves: [] | |||
}, { | |||
name: 'ELTS', | |||
icon: <PersonSpeakerIcon />, | |||
shelves: [] | |||
}] | |||
}; | |||
export const Home: React.FC = () => { | |||
const [isAddWordModalOpen, setAddWordModalState] = useState<boolean>(false); | |||
return <section className="page"> | |||
<header className={styles.pageHeader}> | |||
@@ -42,8 +83,8 @@ export const Home: React.FC = () => { | |||
}} | |||
} /> | |||
{/* eslint-disable-next-line */} | |||
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSERA5Pm3aRBV7AaI8tvpZfzpD24ZgrU1_8NA&usqp=CAU" alt="profile-image" /> | |||
<InternBadge /> | |||
<img src={userProfileData.image} alt="profile-image" /> | |||
{ userProfileData.medal.icon } | |||
</div> | |||
<div className={styles.userDetails}> | |||
<h2> Neymar Junior </h2> | |||
@@ -118,86 +159,30 @@ export const Home: React.FC = () => { | |||
</button> | |||
</header> | |||
<ul> | |||
<li> | |||
<div className={styles.progress}> | |||
<CircularProgressbar value={30} strokeWidth={7} | |||
styles={{ | |||
path: { | |||
stroke: 'white', | |||
strokeLinecap: 'round', | |||
}, | |||
trail: { | |||
stroke: 'rgba(255, 255, 255, 0.25)', | |||
strokeLinecap: 'round', | |||
}} | |||
} /> | |||
<span className={styles.text}> 30% </span> | |||
</div> | |||
<h5> All Words </h5> | |||
<p> Vocabulary </p> | |||
<p> 1.2K Words </p> | |||
</li> | |||
<li> | |||
<div className={styles.progress}> | |||
<CircularProgressbar value={50} strokeWidth={7} | |||
styles={{ | |||
path: { | |||
stroke: 'white', | |||
strokeLinecap: 'round', | |||
}, | |||
trail: { | |||
stroke: 'rgba(255, 255, 255, 0.25)', | |||
strokeLinecap: 'round', | |||
}} | |||
} /> | |||
<span className={styles.text}> 50% </span> | |||
</div> | |||
<h5> IELTS Fundamentals </h5> | |||
<p> IELTS </p> | |||
<p> 250 Words </p> | |||
</li> | |||
<li> | |||
<div className={styles.progress}> | |||
<CircularProgressbar value={10} strokeWidth={7} | |||
styles={{ | |||
path: { | |||
stroke: 'white', | |||
strokeLinecap: 'round', | |||
}, | |||
trail: { | |||
stroke: 'rgba(255, 255, 255, 0.25)', | |||
strokeLinecap: 'round', | |||
}} | |||
} /> | |||
<span className={styles.text}> 10% </span> | |||
</div> | |||
<h5> GRE Fundamentals </h5> | |||
<p> GRE </p> | |||
<p> 456 Words </p> | |||
</li> | |||
<li> | |||
<div className={styles.progress}> | |||
<CircularProgressbar value={25} strokeWidth={7} | |||
styles={{ | |||
path: { | |||
stroke: 'white', | |||
strokeLinecap: 'round', | |||
}, | |||
trail: { | |||
stroke: 'rgba(255, 255, 255, 0.25)', | |||
strokeLinecap: 'round', | |||
}} | |||
} /> | |||
<span className={styles.text}> 25% </span> | |||
</div> | |||
<h5> Sapiens </h5> | |||
<p> Book </p> | |||
<p> 125 Words </p> | |||
</li> | |||
{ userProfileData.categories.map(category => { | |||
return category.shelves.map(shelf => { | |||
return <li key={shelf.name}> | |||
<div className={styles.progress}> | |||
<CircularProgressbar value={shelf.words.length > 0 ? (shelf.revisedWords.length * 100/ shelf.words.length) : 0} strokeWidth={7} | |||
styles={{ | |||
path: { | |||
stroke: 'white', | |||
strokeLinecap: 'round', | |||
}, | |||
trail: { | |||
stroke: 'rgba(255, 255, 255, 0.25)', | |||
strokeLinecap: 'round', | |||
}} | |||
} /> | |||
<span className={styles.text}> { shelf.words.length > 0 ? (shelf.revisedWords.length * 100/ shelf.words.length) : 0 }% </span> | |||
</div> | |||
<h5> { category.name } </h5> | |||
<p> { shelf.name } </p> | |||
<p> { shelf.words.length } words </p> | |||
</li> | |||
}) | |||
}) } | |||
</ul> | |||
</section> | |||
@@ -215,42 +200,17 @@ export const Home: React.FC = () => { | |||
</button> | |||
</header> | |||
<ul> | |||
<li> | |||
<div className={styles.icon}> | |||
<TimeIcon /> | |||
</div> | |||
<div className={styles.info}> | |||
<label> Vocabulary </label> | |||
<span> 5 Shelves </span> | |||
</div> | |||
</li> | |||
<li> | |||
<div className={styles.icon}> | |||
<BookMarkIcon /> | |||
</div> | |||
<div className={styles.info}> | |||
<label> Books </label> | |||
<span> 3 Shelves </span> | |||
</div> | |||
</li> | |||
<li> | |||
<div className={styles.icon}> | |||
<PersonSpeakerIcon /> | |||
</div> | |||
<div className={styles.info}> | |||
<label> IELTS </label> | |||
<span> 5 Shelves </span> | |||
</div> | |||
</li> | |||
<li> | |||
<div className={styles.icon}> | |||
<BrainIcon /> | |||
</div> | |||
<div className={styles.info}> | |||
<label> GRE </label> | |||
<span> 2 Shelves </span> | |||
</div> | |||
</li> | |||
{ userProfileData.categories.map(category => { | |||
return <li key={category.name}> | |||
<div className={styles.icon}> | |||
{ category.icon } | |||
</div> | |||
<div className={styles.info}> | |||
<label> { category.name } </label> | |||
<span> { category.shelves.length } Shelves </span> | |||
</div> | |||
</li> | |||
})} | |||
</ul> | |||
</section> | |||
@@ -1,8 +0,0 @@ | |||
import { IMedal } from "../structure/medals"; | |||
export const ALL_MEDALS: Array<IMedal> = [{ | |||
name: 'Intern', | |||
minValue: 0, | |||
maxValue: 100, | |||
icon: '' | |||
}] |
@@ -2,6 +2,6 @@ import { IShelf } from "./shelf"; | |||
export type ICategory = { | |||
name: string, | |||
icon: string, | |||
icon: JSX.Element, | |||
shelves: Array<IShelf> | |||
}; |
@@ -2,5 +2,5 @@ export type IMedal = { | |||
name: string, | |||
minValue: number, | |||
maxValue: number, | |||
icon: string, | |||
icon: JSX.Element, | |||
}; |
@@ -1,6 +1,7 @@ | |||
import { IWord } from "./word"; | |||
export type IShelf = { | |||
name: string, | |||
words: Array<IWord>, | |||
revisedWords: Array<IWord>, | |||
description: string, | |||