Browse Source

Add Shelf UI

master
kj1352 4 years ago
parent
commit
d26730ada2
10 changed files with 403 additions and 75 deletions
  1. +4
    -0
      src/App.tsx
  2. +2
    -2
      src/assets/icons/Close.svg
  3. +247
    -0
      src/components/add-shelf/AddShelf.module.scss
  4. +55
    -0
      src/components/add-shelf/AddShelf.tsx
  5. +9
    -5
      src/components/add-word/AddWord.module.scss
  6. +69
    -53
      src/components/add-word/AddWord.tsx
  7. +4
    -0
      src/components/categories/Categories.module.scss
  8. +5
    -1
      src/components/home/Home.module.scss
  9. +7
    -13
      src/components/home/Home.tsx
  10. +1
    -1
      src/components/tabs/Tabs.tsx

+ 4
- 0
src/App.tsx View File

@@ -3,12 +3,16 @@ import { Categories } from './components/categories/Categories';
import { Revise } from './components/revise/Revise';
import { Tabs } from "./components/tabs/Tabs";
import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
import { AddWord } from "./components/add-word/AddWord";
import { AddShelf } from "./components/add-shelf/AddShelf";

function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/home" component={Home} />
<Route path="/add-word" component={AddWord} />
<Route path="/add-shelf" component={AddShelf} />
<Route path="/categories" component={Categories} />
<Route path="/revise" component={Revise} />
<Redirect from="/" to="/home" />


+ 2
- 2
src/assets/icons/Close.svg View File

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20.36" height="20.014" viewBox="0 0 20.36 20.014">
<g id="Group_11" data-name="Group 11" transform="translate(-17.641 -24)">
<path id="back-light" d="M18.365,19.53l-8.81-8.666L18.365,2.2,17,.857,6.857,10.869,17,20.871Z" transform="translate(19.635 23.143)" fill="#fff" fill-rule="evenodd"/>
<path id="back-light-2" data-name="back-light" d="M11.508,18.673,2.7,10.007l8.81-8.666L10.146,0,0,10.012l10.146,10Z" transform="translate(29.148 44.014) rotate(180)" fill="#fff" fill-rule="evenodd"/>
<path id="back-light" d="M18.365,19.53l-8.81-8.666L18.365,2.2,17,.857,6.857,10.869,17,20.871Z" transform="translate(19.635 23.143)" fill-rule="evenodd"/>
<path id="back-light-2" data-name="back-light" d="M11.508,18.673,2.7,10.007l8.81-8.666L10.146,0,0,10.012l10.146,10Z" transform="translate(29.148 44.014) rotate(180)" fill-rule="evenodd"/>
</g>
</svg>

+ 247
- 0
src/components/add-shelf/AddShelf.module.scss View File

@@ -0,0 +1,247 @@
.createShelfModal {
background-color: var(--creamy-white);
z-index: 2;
width: 100vw;
height: 100vh;
overflow: auto;
opacity: 0;
position: relative;
animation: fadeIn 0.3s forwards;

@keyframes fadeIn {
0% {
opacity: 0;
transform: translateY(10vh);
} 100% {
opacity: 1;
transform: translateY(0vh);
}
}
}

.modalHeader {
background-color: var(--orange);
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 4.5rem;
padding-top: 0.5rem;
h4 {
flex-grow: 1;
padding-left: 4rem;
color: white;
font-size: 1.5rem;
text-align: center;
font-weight: 500;
}

button {
margin-left: auto;
margin-right: 1rem;
width: 4rem;
height: 4rem;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
border: none;

svg {
width: 1.5rem;
fill: white;
}
}
}

.form {
border-radius: 3rem;
background-color: var(--creamy-white);
overflow: hidden;
margin-top: -4rem;
padding: 2rem;

input {
border: none;
height: 4rem;
width: 100%;
display: block;
border-radius: 3rem;
box-shadow: 0px 2px 10px -5px inset var(--light-grey);
padding: 0 1.5rem;
font-size: 1.2rem;
margin-bottom: 1.5rem;
background-color: #efe6d6;
}

textarea {
background-color: #efe6d6;
font-size: 1.2rem;
padding: 1rem 1.5rem;
box-shadow: 0px 2px 10px -5px inset var(--light-grey);
border: none;
resize: none;
display: block;
width: 100%;
height: 10rem;
border-radius: 1.5rem;
margin-bottom: 1.5rem;
}
}

.blockHeader {
display: flex;
align-items: center;
justify-content: flex-start;

h5 {
font-size: 1.2rem;
font-weight: 600;
color: var(--black);
flex-grow: 1;

svg {
width: 2rem;
height: 2rem;
fill: var(--black);
vertical-align: middle;
margin-right: 1rem;
}
}

button, a {
background-color: var(--teal);
width: 3rem;
height: 3rem;
border: none;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-left: 1rem;

&.expandButton {
background-color: var(--red);
}

svg {
fill: white;
width: 1.2rem;
}
}
}

.Grid {
padding: 0 0.5rem;

ul {
list-style: none;
display: grid;
grid-template-columns: 1fr 1fr;
}

li {
display: flex;
justify-content: space-between;
align-items: center;
margin: 1rem 0;

&:nth-child(1) .icon {
background-color: var(--orange);
}

&:nth-child(2) .icon {
background-color: var(--blue);
}

&:nth-child(3) .icon {
background-color: var(--red);
}

&:nth-child(4) .icon {
background-color: var(--teal);
}
}

.icon {
width: 4.5rem;
height: 4.5rem;
background-color: var(--grey);
display: flex;
align-items: center;
justify-content: center;
border-radius: 1rem;

svg {
fill: white;
width: 2rem;
}
}

.info {
width: calc(100% - 5.5rem);

label, span {
display: block;
}

label {
font-size: 1.2rem;
color: var(--black);
font-weight: 700;
}

span {
font-size: 1rem;
color: var(--grey);
}
}
}

.toggleHolder {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 2rem 0.5rem;

label {
font-size: 1.2rem;
color: var(--black);
font-weight: 600;
}

.toggle {
background-color: #efe6d6;
width: 4rem;
height: 2rem;
border-radius: 3rem;
box-shadow: 0px 0px 10px -5px inset var(--light-grey);

span {
width: 2rem;
height: 2rem;
background-color: var(--red);
border-radius: 50%;
display: block;
transform: scale(0.8);
}
}
}

.publishButton {
width: 9rem;
height: 3.5rem;
background-color: var(--teal);
font-size: 1.2rem;
font-weight: 500;
color: white;
display: block;
margin: 2rem auto;
border: none;
border-radius: 3rem;
position: fixed;
left: calc(50% - 4.5rem);
bottom: 1rem;
z-index: 1;
}

+ 55
- 0
src/components/add-shelf/AddShelf.tsx View File

@@ -0,0 +1,55 @@
import React from "react";
import styles from './AddShelf.module.scss';
import { ReactComponent as CloseIcon } from '../../assets/icons/close.svg';
import { ReactComponent as PlusIcon } from '../../assets/icons/plus.svg';
import { userProfileData } from "../home/Home";

export const AddShelf: React.FC = () => {
return <section className={styles.createShelfModal}>

<header className={styles.modalHeader}>
<h4> Create New Shelf </h4>
<button onClick={() => { window.history.back() }}>
<CloseIcon />
</button>
</header>

<section className={styles.form}>
<input type="text" placeholder={'Shelf Name'} />
<textarea placeholder={'Add description'}></textarea>

<section className={styles.Grid}>
<header className={styles.blockHeader}>
<h5>
Choose a category
</h5>
<button>
<PlusIcon />
</button>
</header>
<ul>
{ 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>

<section className={styles.toggleHolder}>
<label> Public </label>
<div className={styles.toggle}>
<span></span>
</div>
</section>

<button className={styles.publishButton}> Publish </button>
</section>
</section>
}

+ 9
- 5
src/components/add-word/AddWord.module.scss View File

@@ -1,13 +1,11 @@
.modalPage {
background-color: var(--creamy-white);
position: fixed;
top: 0;
left: 0;
z-index: 2;
width: 100vw;
height: 100vh;
overflow: auto;
opacity: 0;
position: relative;
animation: fadeIn 0.3s forwards;

@keyframes fadeIn {
@@ -234,13 +232,18 @@

.shelfList {
list-style: none;
padding: 1rem 2rem;
background-color: var(--creamy-white);
border-top-right-radius: 3rem;
border-top-left-radius: 3rem;
margin: -4rem 0;
min-height: 5rem;
padding: 2rem;

header {
margin: 0 auto 1rem;
h5 {
font-weight: 300;
font-size: 1.2rem;
font-size: 1.3rem;
color: var(--black);
}
}
@@ -313,6 +316,7 @@
box-shadow: 0px 0px 5px var(--creamy-white);
font-weight: 600;
color: var(--black);
font-size: 1.3rem;

span {
width: 3rem;


+ 69
- 53
src/components/add-word/AddWord.tsx View File

@@ -8,14 +8,10 @@ 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";
import { NavLink } from "react-router-dom";


type OwnProps = {
hideModal: () => void
};

export const AddWord: React.FC<OwnProps> = (props: OwnProps) => {
const [searchResult, setSearchResult] = useState<Array<IWord>>([]);
export const AddWord: React.FC = () => {
const [searchWordResult, setSearchResult] = useState<Array<IWord>>([]);
const [selectedWord, setSelectedWord] = useState<IWord>();

const searchWords = (searchWord: string) => {
@@ -32,63 +28,83 @@ export const AddWord: React.FC<OwnProps> = (props: OwnProps) => {

return <section className={styles.modalPage}>
<header className={styles.navHeader}>
<button onClick={props.hideModal}>
<button onClick={() => {
if (selectedWord) {
setSelectedWord(undefined);
} else {
window.history.back()
}
}}>
<ChevronLeft />
</button>
<h5> Add a Word </h5>
{ !selectedWord && <h5> Add a Word </h5> }
{ selectedWord && <h5> Add to Shelf </h5> }
<figure>
<figure style={{ opacity: selectedWord ? 0 : 1 }}>
{/* eslint-disable-next-line */}
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSERA5Pm3aRBV7AaI8tvpZfzpD24ZgrU1_8NA&usqp=CAU" alt="profile-image" />
<img src={ userProfileData.image } 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 />
{ !selectedWord && <section>
<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>
</div>

<ul className={styles.searchResult}>
{ !selectedWord && 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} 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>
<ul className={styles.searchResult}>
{ searchWordResult.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} onClick={() => setSelectedWord(word)}> <AddIcon /> Add </button>
</li>
})
}) }
}) }
</ul>
</section> }


{ selectedWord && <section>
<div className={styles.searchBarHolder}>
<div className={styles.searchBar}>
<input type="text" placeholder={'Search shelves'}/>
<SearchIcon />
</div>
</div>

<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> }
<NavLink to={'/add-shelf'} className={styles.AddShelfButton}> <span> <AddIcon /> </span> Create New Shelf </NavLink>
</ul>
</section> }
</section>
}

+ 4
- 0
src/components/categories/Categories.module.scss View File

@@ -4,6 +4,10 @@
padding: 1.5rem 0;
position: relative;

svg {
transform: scale(0.9);
}

figure {
display: block;
position: absolute;


+ 5
- 1
src/components/home/Home.module.scss View File

@@ -2,6 +2,10 @@
background-color: var(--orange);
text-align: center;
padding: 1rem 0 0.5rem;

svg {
transform: scale(0.9);
}
}

.upfold {
@@ -119,7 +123,7 @@
}
}

button {
button, a {
background-color: var(--teal);
width: 3rem;
height: 3rem;


+ 7
- 13
src/components/home/Home.tsx View File

@@ -16,8 +16,8 @@ import { ReactComponent as PersonSpeakerIcon } from '../../assets/icons/user-spe
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";
import { NavLink } from "react-router-dom";


export var userProfileData : IProfile = {
@@ -61,8 +61,6 @@ export var userProfileData : IProfile = {
};

export const Home: React.FC = () => {
const [isAddWordModalOpen, setAddWordModalState] = useState<boolean>(false);
return <section className="page">

<header className={styles.pageHeader}>
@@ -99,10 +97,10 @@ export const Home: React.FC = () => {
</div>
</section>

<div className={styles.searchBar}>
<input type="text" placeholder={'Search and add a word'} onClick={() => setAddWordModalState(true)} />
<NavLink to={'/add-word'} className={styles.searchBar}>
<input type="text" placeholder={'Search and add a word'} />
<SearchIcon />
</div>
</NavLink>

<section className={styles.List}>
<header className={styles.blockHeader}>
@@ -154,9 +152,9 @@ export const Home: React.FC = () => {
<button className={styles.expandButton}>
<ExpandIcon />
</button>
<button>
<NavLink to={'/add-shelf'}>
<PlusIcon />
</button>
</NavLink>
</header>
<ul>
{ userProfileData.categories.map(category => {
@@ -210,12 +208,8 @@ export const Home: React.FC = () => {
<span> { category.shelves.length } Shelves </span>
</div>
</li>
})}
})}
</ul>
</section>


{ isAddWordModalOpen && <AddWord hideModal={() => { setAddWordModalState(false); }} /> }

</section>
}

+ 1
- 1
src/components/tabs/Tabs.tsx View File

@@ -12,7 +12,7 @@ export const Tabs: React.FC = () => {
return <section className={styles.tabs}>
<NavLink to={'/home'} activeClassName={styles.active}>
<HomeIcon />
</NavLink >
</NavLink>
<NavLink to={'/categories'} activeClassName={styles.active}>
<GridIcon />
</NavLink >


Loading…
Cancel
Save