Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@
"react-helmet": "^6.1.0",
"react-icons": "^4.3.1",
"react-organizational-chart": "^2.1.1",
"react-router-dom": "6",
"react-redux": "^8.0.1",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"react-shimmer-effect": "^1.0.9",
"redux": "^4.2.0",
"redux-persist": "^6.0.0",
"reselect": "^4.1.5",
"web-vitals": "^2.1.0"
},
"scripts": {
Expand Down
4 changes: 2 additions & 2 deletions src/common/routing/RouteDefs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ const RouteDefs = () => {
</Route>
<Route path="/ideas" element={<PlayIdeas />} />
<Route path="/*" element={<PageNotFound />} />

</Routes>
<Footer />
</BrowserRouter>
);
};

export default RouteDefs;
export default RouteDefs;
17 changes: 16 additions & 1 deletion src/meta/play-meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
ExpandingCards,
AnalogClock,
PasswordGenerator,
Quizeo,
WhyTypescript,
NetlifyCardGame,
RegistrationForm,
Expand Down Expand Up @@ -233,8 +234,22 @@ export const plays = [
blog: "",
video: "",
featured: true,

}, {
id: 'pl-quizeo',
name: 'Quizeo',
description: 'Quizeo is a react app to play quiz about your favourite movies and series.',
component: () => {return <Quizeo />},
path: '/plays/quizeo',
level: 'Advanced',
tags: 'React-router,Hooks,react-redux,reselect',
github: 'vasantisuthar',
cover: '',
blog: 'https://vasantisuthar.hashnode.dev/',
video: '',
language: 'js'
},
{
{
id: "pl-password-generator",
name: "Password Generator",
description:
Expand Down
2 changes: 2 additions & 0 deletions src/plays/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ export { default as RegistrationForm } from "plays/registration-form/Registratio
export { default as Calendar } from "plays/calendar/Calendar";
export { default as FunQuiz } from "plays/fun-quiz/FunQuiz";
export { default as TicTacToeGame } from "plays/tic-tac-toe-game/TicTacToeGame";
export { default as Quizeo } from 'plays/quizeo/src/Quizeo';
//add export here
15 changes: 15 additions & 0 deletions src/plays/quizeo/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Quizeo

Quizeo is a react fun project to play quiz around favourite movies and series, if you have watched.

## What you will learn
The app demonstrates
- the use of reusable components, shows you how to divide your react app into components
- use of react-redux
- use of react-redux with hooks
- use of reselect for better memoization and cache management
- use of ES6 features

The app uses redux store to store the state and data of the app globally and is fetched with the help of selectors 'react-reselect' to implement memoization to the app. Also each component contains its own CSS for easy implementation of design.

Happy learning!
Binary file added src/plays/quizeo/cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions src/plays/quizeo/src/Quizeo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { getPlayById } from 'meta/play-meta-util';
import PlayHeader from 'common/playlists/PlayHeader';
import { store,persistor } from './redux/store';
import { useEffect } from 'react';
import { setScore, setQuestionNo } from "./redux/questions/questions-action";
import Directory from "./components/directory/directory.component";
import Header from "./components/header/header.component";
import { Provider} from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import './quizeo.css'

function Quizeo(props) {
// Do not remove the below lines.
// The following code is to fetch the current play from the URL
const { id } = props;
const play = getPlayById(id);

// Your Code Start below.
useEffect(() =>{
store.dispatch(setScore());
store.dispatch(setQuestionNo());
})
return (
<>
<div className="play-details">
<PlayHeader play={play} />
<div className="play-details-body quizeo">
{/* Your Code Starts Here */}
<Provider store = {store}>
<PersistGate persistor={persistor}>
<Header/>
<Directory/>
</PersistGate>
</Provider>
{/* Your Code Ends Here */}
</div>
</div>
</>
);
}

export default Quizeo;
29 changes: 29 additions & 0 deletions src/plays/quizeo/src/components/directory/directory.component.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import { selectDirectorySection } from "../../redux/directory/directory-selectors";
import MoviePage from "../../pages/moviePage/moviePage.component";
import { useSelector} from 'react-redux';
import MenuItem from "../menu-item/menuItem.component";
import { selectQuestionIndex, selectClickedAction} from "../../redux/movie/movieSelector";

import './directory.styles.css';
const Directory = () => {

let questionIndex = useSelector(selectQuestionIndex);
let isClick = useSelector(selectClickedAction);
const sections = useSelector(selectDirectorySection);

return (
<div>
{
isClick ? <MoviePage categoryId={questionIndex}/> :
<div className="directoryMenu">
{sections.map(({id, ...otherSectionComponent}) => (
<MenuItem key={id} {...otherSectionComponent}/>
))}
</div>
}
</div>
);
}

export default Directory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.quizeo .directoryMenu{
margin: 3rem;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
15 changes: 15 additions & 0 deletions src/plays/quizeo/src/components/header/header.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import './header.styles.css';
import { isClicked } from '../../redux/questions/questions-action';

const Header = () => {
let dispatch = useDispatch();
return (
<div>
<h1 className="header" onClick={() => dispatch(isClicked())}>Quizeo</h1>
</div>
);
}

export default Header;
9 changes: 9 additions & 0 deletions src/plays/quizeo/src/components/header/header.styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.quizeo .header{
cursor: pointer;
margin-top: 1.5rem;
margin-bottom: 3.5rem;
font-size: 3rem;
line-height: 1;
font-weight: 700;
text-decoration: none;
}
35 changes: 35 additions & 0 deletions src/plays/quizeo/src/components/menu-item/menu-item.styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.quizeo .menu-item{
display: flex;
position: relative;
margin: 0.25rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 18rem;
border-width: 4px;
opacity: 0.9;
}

.quizeo .image-container{
background-position: center;
background-size: cover;
width: 100%;
height: 18rem;
}

.quizeo .image-content{
position: absolute;
padding: 1.25rem;
background-color: #ffffff;
color: #000000;
font-weight: 600;
border-width: 2px;
cursor: pointer;
opacity: 0.8;
}

.quizeo .image-content h1{
font-size: 1.125rem;
line-height: 1.75rem;
}
21 changes: 21 additions & 0 deletions src/plays/quizeo/src/components/menu-item/menuItem.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import { useDispatch} from "react-redux"
import { displayQuestionComponent, isClicked } from "../../redux/questions/questions-action";

import './menu-item.styles.css'

const MenuItem = ({title, imageUrl, linkUrl}) => {
const dispatch = useDispatch();

return (
<div className="menu-item">
<div className="image-container" style={{backgroundImage:`url(${imageUrl})`}}/>
<div className="image-content"
onClick={() => {dispatch(displayQuestionComponent(linkUrl)); dispatch(isClicked())}}>
<h1>{title}</h1>
</div>
</div>
);
}

export default MenuItem;
59 changes: 59 additions & 0 deletions src/plays/quizeo/src/components/questions/questions.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { ScoreModel } from "../../pages/score-page/score.component";
import { addScore,showModel } from "../../redux/questions/questions-action";
import { increaseQuestionNo } from "../../redux/questions/questions-action";
import { selectQuestionNo, selectHiddenState } from "../../redux/movie/movieSelector";

import './questions.styles.css';

const Questions = (collection) => {
const counter = useSelector(selectQuestionNo);
const hidden = useSelector(selectHiddenState);
const dispatch = useDispatch();
let obj;
return (
<div className="question-container">
{Object.keys(collection).map((item,i) => (
<div className={`${hidden ? '' : 'question-background'} question-model`}>
{/* movie title */}
<p className="category-title"><span className="title">
{collection[item].title}</span>
</p>
<div className="questions-section">
{/* question */}
<p className="question-title">
{counter + 1}.{collection[item].questions[counter].question}
</p>

{/* options */}
<div className="options-section">
{Object.keys(collection[item].questions[counter].options).map((option, i) =>(
<button className="option-button"
value={collection[item].questions[counter].options[option]}
// eslint-disable-next-line no-undef
onClick={(e) => {
obj = {
answer :e.target.value,
correct : collection[item].questions[counter].answer
}
}}
>
{collection[item].questions[counter].options[option]}
</button>
))}
<br></br>
{counter === collection[item].questions.length-1 ?
<button className="submit-answer" onClick= {() => {dispatch(addScore(obj));dispatch(showModel())}} >submit</button> :
<button type="button" className="submit-answer" onClick={() => {dispatch(addScore(obj)); dispatch(increaseQuestionNo())}}>Next</button>}
</div>
</div>
</div>
))}
{hidden ? null: <ScoreModel questionNo = {counter}/>}
</div>
);
}


export default Questions;
Loading