Parcourir la source

Shelf details page

master
kj1352 il y a 4 ans
Parent
révision
9c1736e9d5
4 fichiers modifiés avec 520 ajouts et 8 suppressions
  1. +86
    -1
      src/components/add-word/AddWord.module.scss
  2. +12
    -4
      src/components/add-word/AddWord.tsx
  3. +362
    -0
      src/components/shelf-details/ShelfDetails.module.scss
  4. +60
    -3
      src/components/shelf-details/ShelfDetails.tsx

+ 86
- 1
src/components/add-word/AddWord.module.scss Voir le fichier

@@ -88,7 +88,35 @@
margin-bottom: 1.5rem;
background-color: white;

&:nth-child(2n) {
&:nth-child(4n - 4) {
&::before {
background-color: var(--orange);
}

header {
h4 {
span {
color: var(--orange);
}
}
button {
background-color: var(--orange);
}
}

.description {
span, p {
color: var(--orange);
}
}

.addButton {
background-color: var(--teal);
}
}

&:nth-child(4n - 3) {
&::before {
background-color: var(--teal);
}
@@ -116,6 +144,63 @@
}
}

&:nth-child(4n - 2) {
&::before {
background-color: var(--blue);
}

header {
h4 {
span {
color: var(--blue);
}
}
button {
background-color: var(--blue);
}
}

.description {
span, p {
color: var(--blue);
}
}

.addButton {
background-color: var(--blue);
}
}


&:nth-child(4n - 1) {
&::before {
background-color: var(--red);
}

header {
h4 {
span {
color: var(--red);
}
}
button {
background-color: var(--red);
}
}

.description {
span, p {
color: var(--red);
}
}

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

&::before {
content: '';
position: absolute;


+ 12
- 4
src/components/add-word/AddWord.tsx Voir le fichier

@@ -7,12 +7,13 @@ import { ReactComponent as AddIcon } from '../../assets/icons/plus.svg';

import { IWord } from "../../structure/word";
import { ALL_WORDS } from "../../data/all-words";
import { NavLink } from "react-router-dom";
import { NavLink, useHistory } from "react-router-dom";
import { userProfileData } from "../../App";

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

const searchWords = (searchWord: string) => {
if (searchWord.length > 0) {
@@ -22,7 +23,7 @@ export const AddWord: React.FC = () => {
setSearchResult(result);
} else {
setSearchResult([]);
setSearchResult(ALL_WORDS);
}
}

@@ -89,7 +90,14 @@ export const AddWord: React.FC = () => {
{ 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);
let findWord = userProfileData.categories[categoryIndex].shelves[shelfIndex].words.find(word => word.name.toLowerCase().includes(selectedWord.name.toLowerCase()));

if (findWord) {
alert("Word already Present!");
} else {
userProfileData.categories[categoryIndex].shelves[shelfIndex].words.push(selectedWord);
history.push('/shelf-details/category_id=' + categoryIndex + '&&shelf_id=' + shelfIndex);
}
}}>
<div className={styles.icon}>
{ category.icon }


+ 362
- 0
src/components/shelf-details/ShelfDetails.module.scss Voir le fichier

@@ -37,4 +37,366 @@
border: 1px solid var(--creamy-white);
}
}
}

.tabHeading {
background-color: transparent;
position: relative;
padding: 1.5rem 0 8rem;
text-align: center;

&::before {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
background-color: var(--teal);
border-top-left-radius: 3rem;
border-top-right-radius: 3rem;
}

&>* {
position: relative;
}

h4 {
color: white;
font-size: 2.2rem;
font-weight: 600;
}

p {
color: white;
font-size: 1.4rem;
}

.moreButton {
position: absolute;
right: 2rem;
top: 2.5rem;
width: 2rem;
height: 5rem;
display: flex;
align-items: flex-start;
justify-content: center;
background-color: transparent;
border: none;

svg {
fill: white;
width: 1.8rem;
height: 1.8rem;
}
}

.progressHolder {
padding: 0 4rem;
margin-top: 1rem;
display: flex;
align-items: center;
justify-content: space-between;

.progressBarHolder {
width: calc(100% - 6rem);
.progressBar {
width: 100%;
overflow: hidden;
height: 1rem;
border-radius: 1rem;
background-color: white;
position: relative;
margin-top: 0.3rem;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: var(--red);
opacity: 0.6;
}

span {
position: absolute;
left: 0;
top: 0;
width: 0%;
height: 100%;
background-color: var(--red);
border-radius: inherit;
}
}
}

.reviseButton {
width: 4.5rem;
height: 4.5rem;
background-color: white;
box-shadow: 0px 0px 5px var(--grey);
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
border: none;

svg {
fill: var(--teal);
width: 2rem;
height: 2rem;
}
}

.info {
display: flex;
width: 100%;
justify-content: space-between;

h6 {
color: white;
font-size: 1.4rem;
}

span {
color: white;
font-size: 1.4rem;
}
}
}
}

.searchHolder {
position: relative;
&::before {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
background-color: var(--creamy-white);
border-top-left-radius: 3rem;
border-top-right-radius: 3rem;
}

&>* {
position: relative;
}

.searchBar {
background-color: white;
display: flex;
border-radius: 3rem;
height: 5rem;
width: calc(100% - 6rem);
margin: -2.5rem auto 0;
align-items: center;
justify-content: space-between;
box-shadow: 0px 5px 30px -20px var(--grey);
transform: translateY(-2.5rem);
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: -2.5rem 0;
min-height: 5rem;
padding: 2rem;

li {
position: relative;
overflow: hidden;
border-radius: 2rem;
padding: 1rem 1.5rem;
margin-bottom: 1.5rem;
background-color: white;

&:nth-child(4n - 4) {
&::before {
background-color: var(--orange);
}

header {
h4 {
span {
color: var(--orange);
}
}
button {
background-color: var(--orange);
}
}

.description {
span, p {
color: var(--orange);
}
}
}

&:nth-child(4n - 3) {
&::before {
background-color: var(--teal);
}

header {
h4 {
span {
color: var(--teal);
}
}
button {
background-color: var(--teal);
}
}

.description {
span, p {
color: var(--teal);
}
}
}

&:nth-child(4n - 2) {
&::before {
background-color: var(--blue);
}

header {
h4 {
span {
color: var(--blue);
}
}
button {
background-color: var(--blue);
}
}

.description {
span, p {
color: var(--blue);
}
}
}


&:nth-child(4n - 1) {
&::before {
background-color: var(--red);
}

header {
h4 {
span {
color: var(--red);
}
}
button {
background-color: var(--red);
}
}

.description {
span, p {
color: var(--red);
}
}
}

&::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: var(--orange);
opacity: 0.4;
}

&>* {
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);
}
}
}
}

+ 60
- 3
src/components/shelf-details/ShelfDetails.tsx Voir le fichier

@@ -1,11 +1,17 @@
import React from "react";
import React, { useState } from "react";
import styles from './ShelfDetails.module.scss';
import { ReactComponent as ChevronLeft } from '../../assets/icons/chevron-left.svg';
import { useLocation } from "react-router-dom";
import { NavLink, useLocation } from "react-router-dom";
import queryString from 'query-string';
import { ICategory } from "../../structure/category";
import { IShelf } from "../../structure/shelf";
import { userProfileData } from "../../App";
import { ReactComponent as BookIcon } from '../../assets/icons/book-sharp.svg';
import { ReactComponent as MoreIcon } from '../../assets/icons/more-alt.svg';
import { ReactComponent as SearchIcon } from '../../assets/icons/bx-search-alt.svg';
import { ReactComponent as SpeakerIcon } from '../../assets/icons/speaker.svg';
import { IWord } from "../../structure/word";
import { ALL_WORDS } from "../../data/all-words";

export const ShelfDetails: React.FC = () => {
const location = useLocation();
@@ -13,6 +19,19 @@ export const ShelfDetails: React.FC = () => {
const shelf_id: any = queryString.parse(location.pathname)['shelf_id'];
const category: ICategory = userProfileData.categories[category_id];
const shelf: IShelf = category.shelves[shelf_id];
const [searchWordResult, setSearchResult] = useState<Array<IWord>>(shelf.words);

const searchWords = (searchWord: string) => {
if (searchWord.length > 0) {
let result = shelf.words.filter((word) => {
return word.name.toLowerCase().includes(searchWord.toLowerCase());
});
setSearchResult(result);
} else {
setSearchResult(shelf.words);
}
}
return <section className="modalPage">
<header className={styles.navHeader}>
@@ -29,9 +48,47 @@ export const ShelfDetails: React.FC = () => {
</header>
<header className={styles.tabHeading}>
<button className={styles.moreButton}>
<MoreIcon />
</button>

<h4> { shelf.name } </h4>
<p> { shelf.words.length } </p>
<p> { shelf.words.length } Words </p>

{ shelf.words.length > 0 && <div className={styles.progressHolder}>
<div className={styles.progressBarHolder}>
<div className={styles.info}> <h6> Revision </h6> <span> { shelf.revisedWords.length * 100/ shelf.words.length }% </span> </div>
<div className={styles.progressBar}> <span className={styles.progress} style={{ width: shelf.revisedWords.length * 100/ shelf.words.length + '%' }}></span> </div>
</div>
<NavLink to={'/revise'} className={styles.reviseButton}>
<BookIcon />
</NavLink>
</div> }
</header>

<section className={styles.searchHolder}>
<div className={styles.searchBar}>
<input type="text" autoFocus={true} placeholder={'Search words'} onChange={(event) => searchWords(event.currentTarget.value)} />
<SearchIcon />
</div>
</section>

<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>
</li>
}) }
</ul>

</section>
}

Chargement…
Annuler
Enregistrer