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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
yarn.lock
55 changes: 34 additions & 21 deletions src/meta/play-meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import {
MovieContainer,
WhyReact,
CounterApp,
States,
SocialCard,
RandomMemeGenerator,
//import play here
States,
SocialCard,
RandomMemeGenerator,
ReactTodoApp,
//import play here
} from "plays";

export const plays = [
{
id: 'pl-0001',
name: 'Why React',
description: 'A simple application to demonstrate JSX usages',
component: () => {return <WhyReact />},
component: () => { return <WhyReact /> },
path: '/plays/why-react',
index: true,
level: 'Beginner',
Expand All @@ -27,7 +28,7 @@ export const plays = [
id: 'pl-0002',
name: 'Clock',
description: 'This application shows the current time and it increases every second',
component: () => {return <CurrentTimer />},
component: () => { return <CurrentTimer /> },
path: '/plays/clock',
level: 'Beginner',
tags: 'JSX, Schedule',
Expand All @@ -39,7 +40,7 @@ export const plays = [
id: 'pl-0003',
name: 'Countdown Timer',
description: 'It is a timer that fires every second and decreases the time',
component: () => {return <CdTimerComp />},
component: () => { return <CdTimerComp /> },
path: '/plays/date-time-counter',
level: 'Intermediate',
tags: 'Schedule, Component Structure, Hooks, Custom Hooks',
Expand All @@ -50,7 +51,7 @@ export const plays = [
id: 'pl-0004',
name: 'Movies',
description: 'A list of movies from API call.',
component: () => {return <MovieContainer />},
component: () => { return <MovieContainer /> },
path: '/plays/movies',
level: 'Intermediate',
tags: 'Fetch Data, Hooks',
Expand All @@ -62,38 +63,38 @@ export const plays = [
id: 'pl-0005',
name: 'Organization Tree',
description: 'A simple org tree',
component: () => {return <BasicTree />},
component: () => { return <BasicTree /> },
path: '/plays/org-tree',
level: 'Intermediate',
tags: 'Recursion, Tree',
github: 'green-roots',
featured: true
}, {
id: 'pl-counter',
name: 'Counter',
id: 'pl-counter',
name: 'Counter',
description: 'A simple counter which increments the value upto a certain limit!',
component: () => {return <CounterApp />},
component: () => { return <CounterApp /> },
path: '/plays/counter',
level: 'Beginner',
tags: 'JSX, State, Props',
github: 'murtuzaalisurti',
featured: true
}, {
id: 'pl-states',
name: 'States',
id: 'pl-states',
name: 'States',
description: 'States in Functional Components',
component: () => {return <States />},
component: () => { return <States /> },
path: '/plays/states',
level: 'Beginner',
tags: 'Hooks,State,JSX',
github: 'Abhishek-90',
cover: '',
blog: 'https://abhishek-90.github.io/My-Portfolio/'
}, {
id: 'pl-social-card',
name: 'Social Card',
id: 'pl-social-card',
name: 'Social Card',
description: 'The Social Card helps you telling who you are using photo, name, and other social footprints.',
component: () => {return <SocialCard />},
component: () => { return <SocialCard /> },
path: '/plays/social-card',
level: 'Intermediate',
tags: 'Form,Events,Complex State',
Expand All @@ -102,17 +103,29 @@ export const plays = [
blog: 'https://blog.greenroots.info/how-to-create-react-form-with-a-single-change-event-handler',
video: ''
}, {
id: 'pl-random-meme-generator',
name: 'Random Meme Generator',
id: 'pl-random-meme-generator',
name: 'Random Meme Generator',
description: 'A project to demonstrate the use of API to fetch random memes! It also demonstrates how you can do event handling!',
component: () => {return <RandomMemeGenerator />},
component: () => { return <RandomMemeGenerator /> },
path: '/plays/random-meme-generator',
level: 'Beginner',
tags: 'JSX,Hooks,API,EventHandling',
github: 'murtuzaalisurti',
cover: '',
blog: '',
video: ''
}, {
id: 'pl-react-todo-app',
name: 'React Todo App',
description: 'It is a simple Todo App which keeps track of your regular work',
component: () => { return <ReactTodoApp /> },
path: '/plays/react-todo-app',
level: 'Beginner',
tags: 'ReactHooks, JavaScript, Css, React State',
github: 'nirban256',
cover: 'https://res.cloudinary.com/atapas/image/upload/v1650866465/demos/cover_y20bzk.png',
blog: '',
video: ''
}, //replace new play item here
];

Expand Down
1 change: 1 addition & 0 deletions src/plays/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export { default as CounterApp } from 'plays/counter/CounterApp';
export { default as States } from 'plays/states/States';
export { default as SocialCard } from 'plays/social-card/SocialCard';
export { default as RandomMemeGenerator } from 'plays/random-meme-generator/RandomMemeGenerator';
export { default as ReactTodoApp } from 'plays/react-todo-app/ReactTodoApp';
//add export here
66 changes: 66 additions & 0 deletions src/plays/react-todo-app/ReactTodoApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { getPlayById } from 'meta/play-meta-util';

import PlayHeader from 'common/playlists/PlayHeader';

import { useState, useEffect } from 'react';

// css file
import './react-todo.css';

// components
import Input from './components/Input';
import TodoList from './components/TodoList';

function ReactTodoApp(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.

const [input, setInput] = useState("");
const [todos, setTodos] = useState([]);
const [status, setStatus] = useState("all");
const [filtered, setFiltered] = useState([]);

useEffect(() => {

const filterHandler = () => {
switch (status) {
case "completed":
setFiltered(todos.filter(todo => todo.completed === true));
break;
case "uncompleted":
setFiltered(todos.filter(todo => todo.completed === false));
break;
default:
setFiltered(todos);
break;
}
}

filterHandler();
}, [status, todos]);

return (
<>
<div className="play-details">
<PlayHeader play={play} />
<div className="play-details-body">
{/* Your Code Starts Here */}
<div className="todo-play-body">
<div className="top">
<h1>Todo List</h1>
</div>
<Input todos={todos} setTodos={setTodos} setInput={setInput} input={input} setStatus={setStatus} />
<TodoList todos={todos} setTodos={setTodos} filtered={filtered} />
</div>
{/* Your Code Ends Here */}
</div>
</div>
</>
);
}

export default ReactTodoApp;
14 changes: 14 additions & 0 deletions src/plays/react-todo-app/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# React-Todo App

It is a Todo App to made with React to keep track of the tasks you plan to complete within a specific amount of time, most probably a day.


## What will you learn?

- Use of `useEffect` hook.
- Event handling for user interaction.
- State management


The file `ReactTodoApp` is the main file along with the css and other files in the component folder required to build the Todo App.
If you want to implement your learnings about states and useEffect hooks try implementing it on your own!
41 changes: 41 additions & 0 deletions src/plays/react-todo-app/components/Input.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { FaPlusSquare } from 'react-icons/fa';

const Input = ({ input, setInput, todos, setTodos, setStatus }) => {

const inputHandler = (e) => {
setInput(e.target.value);
}

const submitHandler = (e) => {
e.preventDefault();
if (input.length > 0) {
setTodos([
...todos, { text: input, completed: false, id: Math.random() * 1000 }
]);
setInput('');
}
}

const statusHandler = (e) => {
setStatus(e.target.value);
}

return (
<form className='form'>
<input onChange={inputHandler} value={input} type="text" className="todo-input" />
<button onClick={submitHandler} className="todo-button" type="submit">
<FaPlusSquare />
</button>
<div className="select">
<select onChange={statusHandler} name="todos" className="filter-todo options">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="uncompleted">Uncompleted</option>
</select>
</div>
</form>
);
}

export default Input;
37 changes: 37 additions & 0 deletions src/plays/react-todo-app/components/Todo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

import { FaCheck, FaTrash } from 'react-icons/fa';

const Todo = ({ text, todo, todos, setTodos }) => {

const deleteHandler = () => {
setTodos(todos.filter((element) => element.id !== todo.id))
}

const completeHandler = () => {
setTodos(todos.map(item => {
if (item.id === todo.id) {
return {
...item, completed: !item.completed
}
}
return item;
}))
}

return (
<div className='todo'>
<li className={`todo-item ${todo.completed ? "completed" : ""}`}>
{text}
</li>
<button onClick={completeHandler} className='complete-btn'>
<FaCheck />
</button>
<button onClick={deleteHandler} className='trash-btn'>
<FaTrash />
</button>
</div>
)
}

export default Todo;
16 changes: 16 additions & 0 deletions src/plays/react-todo-app/components/TodoList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'
import Todo from './Todo';

const TodoList = ({ todos, setTodos, filtered }) => {
return (
<div className="todo-container">
<ul className="todo-list">
{filtered.map((todo) => (
<Todo text={todo.text} key={todo.id} todos={todos} setTodos={setTodos} todo={todo} />
))}
</ul>
</div>
);
}

export default TodoList;
Loading