diff --git a/src/meta/play-meta.js b/src/meta/play-meta.js
index 7b203caf36..8167644dfe 100644
--- a/src/meta/play-meta.js
+++ b/src/meta/play-meta.js
@@ -5,6 +5,7 @@ import {
MovieContainer,
WhyReact,
CounterApp,
+SocialCard,
//import play here
} from "plays";
@@ -75,6 +76,18 @@ export const plays = [
tags: 'JSX, State, Props',
github: 'murtuzaalisurti',
featured: true
+ }, {
+ 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 },
+ path: '/plays/social-card',
+ level: 'Intermediate',
+ tags: 'Form,Events,Complex State',
+ github: 'atapas',
+ cover: '',
+ blog: 'https://blog.greenroots.info/how-to-create-react-form-with-a-single-change-event-handler',
+ video: ''
}, //replace new play item here
];
diff --git a/src/plays/index.js b/src/plays/index.js
index 58f8326fda..03dc2a3696 100644
--- a/src/plays/index.js
+++ b/src/plays/index.js
@@ -6,4 +6,5 @@ export { default as BasicTree } from 'plays/org-tree/BasicTree';
export { default as MovieContainer } from 'plays/movies/MovieContainer';
export { default as WhyReact } from 'plays/why-react/WhyReact';
export { default as CounterApp } from 'plays/counter/CounterApp';
+export { default as SocialCard } from 'plays/social-card/SocialCard';
//add export here
diff --git a/src/plays/social-card/CardDetails.jsx b/src/plays/social-card/CardDetails.jsx
new file mode 100644
index 0000000000..5a2d4d70ba
--- /dev/null
+++ b/src/plays/social-card/CardDetails.jsx
@@ -0,0 +1,157 @@
+import { useState, useContext, useEffect } from "react";
+import { SocialContext } from "./context/SocialContext";
+import { BsGithub, BsTwitter, BsLinkedin } from "react-icons/bs";
+import { CgWebsite } from "react-icons/cg";
+import { AiOutlineMail } from "react-icons/ai";
+
+const CardDetails = () => {
+ // Get the user-filled values from the context
+ const { social } = useContext(SocialContext);
+
+ // Destructure the values from the object.
+ const { name, email, photo, bio, website, twitter, linkedIn, github } =
+ social;
+
+ // We need a file reader to handle the photo uploaded by the user.
+ // We have to perform some computations and extract the actual picture
+ // from the file. So created a state variable to take care of this.
+ const [picture, setPicture] = useState();
+
+ // We have an option to set the theme of the social card.
+ // This state variable is the theme object.
+ const [cardTheme, setCardTheme] = useState({
+ bc: "#f2d6d6",
+ fc: "#212121",
+ link: "#000000",
+ });
+
+ // Perform all calculations to get the profile photo
+ // from the file reader.
+ useEffect(() => {
+ if (photo) {
+ const reader = new FileReader();
+ reader.readAsDataURL(photo[0]);
+ reader.onload = () => {
+ setPicture(reader.result);
+ };
+ }
+ }, [photo]);
+
+ // This method will be called when the user changes the theme
+ const applyTheme = theme => {
+ let bc = '';
+ let fc = '';
+ let link = '';
+ switch (theme) {
+ case "dark":
+ bc = '#212121';
+ fc = '#f2d6d6';
+ link = '#ffffff';
+ break;
+ case "light":
+ bc = '#f2d6d6';
+ fc = '#212121';
+ link = '#000000';
+ break;
+ case "red":
+ bc = '#f44336';
+ fc = '#ffffff';
+ link = '#ffffff';
+ break;
+ case "green":
+ bc = '#4caf50';
+ fc = '#ffffff';
+ link = '#ffffff';
+ break;
+ case "blue":
+ bc = '#2196f3';
+ fc = '#ffffff';
+ link = '#ffffff';
+ break;
+ case "yellow":
+ bc = '#ffeb3b';
+ fc = '#000000';
+ link = '#000000';
+ break;
+ default:
+ break;
+ }
+ setCardTheme({
+ ...cardTheme,
+ 'bc': bc,
+ 'fc': fc,
+ 'link': link
+ });
+ }
+
+ return (
+
+ );
+};
+
+export default CardDetails;
diff --git a/src/plays/social-card/CardForm.jsx b/src/plays/social-card/CardForm.jsx
new file mode 100644
index 0000000000..b23f4e10b3
--- /dev/null
+++ b/src/plays/social-card/CardForm.jsx
@@ -0,0 +1,152 @@
+import { useState, useContext, useEffect, useRef } from "react";
+import { SocialContext } from "./context/SocialContext";
+
+const CardForm = () => {
+ // Declaring the state value with an object that contains
+ // all the information of the social card.
+ const [state, setState] = useState({
+ name: "",
+ email: "",
+ photo: "",
+ bio: "",
+ website: "",
+ twitter: "",
+ linkedIn: "",
+ github: "",
+ });
+
+ // We get the updater function from the context.
+ // It will help us to set the user filled information as the context data
+ // so that, other component can access it.
+ const { setSocial } = useContext(SocialContext);
+
+ // We create a reference to focus on the
+ // first input field of the form.
+ const nameInputRef = useRef(null);
+
+ // This method will be called for the value
+ // change of each of the form fields. Please
+ // note how we handle the file input differently.
+ const handleChange = (evt) => {
+ const name = evt.target.name;
+ const value =
+ evt.target.type === "file" ? evt.target.files : evt.target.value;
+ setState({
+ ...state,
+ [name]: value,
+ });
+ };
+
+ // We set the focus of the name input field.
+ useEffect(() => {
+ nameInputRef.current.focus();
+ }, []);
+
+ // Whenever the state value changes, we set the value
+ // of the context data.
+ useEffect(() => {
+ setSocial(state);
+ }, [state, setSocial]);
+
+ return (
+
+ );
+};
+
+export default CardForm;
diff --git a/src/plays/social-card/Readme.md b/src/plays/social-card/Readme.md
new file mode 100644
index 0000000000..1a5e2e0214
--- /dev/null
+++ b/src/plays/social-card/Readme.md
@@ -0,0 +1,16 @@
+# Social Card
+The `Social Card` project demonstrate many key concepts of ReactJS.
+
+- Form Handling.
+- Managing Complex state data like object and how to update it with the single handler.
+- Usage of React Context with the `useContext` hook.
+- Usage of adding focus to the input element with the `useRef` hook.
+
+If you are planning to look into the code in details, please start with the `SocialCard.jsx` file. You will find that we are initializing the context there and wrapping the form and details component with it.
+
+Please check the `CardForm.jsx` file to understand how form handling works with the object
+as a the state value. We have used a single handler to handle every change in the form.
+
+The `CardDetails.jsx` file is the one that is responsible for the rendering of the details. We also use the theming option there.
+
+Happy Learning!
diff --git a/src/plays/social-card/SocialCard.jsx b/src/plays/social-card/SocialCard.jsx
new file mode 100644
index 0000000000..2d81aec384
--- /dev/null
+++ b/src/plays/social-card/SocialCard.jsx
@@ -0,0 +1,47 @@
+import { useState } from "react";
+import { useLocation } from 'react-router-dom';
+import { getPlayById } from 'meta/play-meta-util';
+
+import PlayHeader from 'common/playlists/PlayHeader';
+
+import CardForm from './CardForm';
+import CardDetails from './CardDetails';
+
+import { SocialContext } from './context/SocialContext';
+
+import "./social-card.css";
+
+function SocialCard() {
+ // The following code is to fetch the current play from the URL
+ const location = useLocation();
+ const { id } = location.state;
+ const play = getPlayById(id);
+
+ // The social state carry the information of the social
+ // in the context. This information is made available
+ // between the Card form and the Card details.
+ const [social, setSocial] = useState({});
+ const value = { social, setSocial };
+
+ return (
+ <>
+
+
+
+
+
Create your Social Card
+
Please fill the form below to create a Social Card for you.