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
15 changes: 14 additions & 1 deletion src/meta/play-meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
ReactTodoApp,
ExpandingCards,
AnalogClock,
//import play here
PasswordGenerator,
//import play here
} from "plays";

export const plays = [
Expand Down Expand Up @@ -185,5 +186,17 @@ export const plays = [
cover: "",
blog: "",
video: "",
}, {
id: 'pl-password-generator',
name: 'Password Generator',
description: 'Its a simple password generator built in react using what user can generate password and customize their requirements in choosing characters and number while generating a medium or strong level password.',
component: () => {return <PasswordGenerator />},
path: '/plays/password-generator',
level: 'Beginner',
tags: 'PasswordGenerator',
github: 'Angryman18',
cover: 'https://securityintelligence.com/wp-content/uploads/2018/10/si-eight-character-password-feature.jpg',
blog: '',
video: ''
}, //replace new play item here
];
1 change: 1 addition & 0 deletions src/plays/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export { default as ReactTodoApp } from 'plays/react-todo-app/ReactTodoApp';
export { default as ExpandingCards } from 'plays/expanding-cards/ExpandingCards';
export { default as AnalogClock } from 'plays/analog-clock/AnalogClock';

export { default as PasswordGenerator } from 'plays/password-generator/PasswordGenerator';
//add export here
205 changes: 205 additions & 0 deletions src/plays/password-generator/PasswordGenerator.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import { getPlayById } from "meta/play-meta-util";

import PlayHeader from "common/playlists/PlayHeader";
import { useEffect, useState } from "react";

import "./password-generator-style.css";
import data from "./data.json";

const config = {
length: 12,
numbers: true,
special: true,
uppercase: true,
lowercase: true,
};

function PasswordGenerator(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 [password, setPassword] = useState({ status: false, password: "" });
const [passwordConfig, setPasswordConfig] = useState({ ...config });
const [error, setError] = useState(false);

// generating lowercase characters
data.lowercase = data?.uppercase?.map((i) => i.toLowerCase());

// generate a random number within limit which is provided
const randomNumberGenerator = (limit) => {
let result = 0;
while (limit) {
result = Math.floor(Math.random() * Math.floor(Math.random() * 100));
if (result < limit) return result;
continue;
}
};

// arrange data to feed the generatePassword function
const arrangeData = () => {
const { numbers, special, uppercase, lowercase } = passwordConfig;

const parseData = (val, key) => {
if (val) return data[key];
return [];
};

const concated = [
...parseData(numbers, "numbers"),
...parseData(special, "special"),
...parseData(uppercase, "uppercase"),
...parseData(lowercase, "lowercase"),
];
return concated;
};

// Generate a random password
const generatePassword = () => {
setError(false);
const concated = arrangeData();
let finalPassword = "";
for (let i = 0; i < passwordConfig.length; i++) {
finalPassword += concated[randomNumberGenerator(concated.length)];
}
return finalPassword;
};

// generate password button click handler
const generateHander = () => {
const finalPassword = generatePassword();
setPassword({ status: false, password: finalPassword });
};

// handling checkbox and updating the config
const handleCheckedItem = (name, checked) => {
const modifiedConfig = { ...passwordConfig };
delete modifiedConfig.length;
delete modifiedConfig.excludeSimilarCharacters;
modifiedConfig[name] = checked;
const values = Object.values(modifiedConfig).filter((i) => i === true);
if (values.length === 0) {
return setError(true);
}
setPasswordConfig({ ...passwordConfig, [name]: checked });
setError(false);
};

// Copy the password to the clipboard
const onCopyClick = (e) => {
e.preventDefault();
navigator.clipboard.writeText(password.password);
setPassword({ ...password, status: true });
};

useEffect(() => {
generateHander();
}, []);

const ErrorBox = () => {
return <p className='error'>You cannot Uncheck All At Once.</p>;
};

return (
<div className='play-details'>
<PlayHeader play={play} />
<div className='play-details-body'>
{/* Your Code Starts Here */}
<div className='main'>
<h1 className='title'>Password Generator</h1>
<section className='section'>
{error && <ErrorBox />}
<div>
<CheckBox
getCheckedItem={handleCheckedItem}
checked={passwordConfig?.uppercase}
name='Uppercase'
id='uppercase'
/>
<CheckBox
getCheckedItem={handleCheckedItem}
checked={passwordConfig?.lowercase}
name='Lowercase'
id='lowercase'
/>
<CheckBox
getCheckedItem={handleCheckedItem}
checked={passwordConfig?.special}
name='Special Char.'
id='special'
/>
<CheckBox
getCheckedItem={handleCheckedItem}
checked={passwordConfig?.numbers}
name='Numbers'
id='numbers'
/>
<div className='checkbox-comp '>
<label>Length</label>
<select
className='select'
onChange={(e) => handleCheckedItem("length", e.target.value)}
value={passwordConfig.length}
>
{[12, 14, 16, 20].map((num) => {
return (
<option key={num} value={num}>
{num}
</option>
);
})}
</select>
</div>
</div>
<div>
<input
type='text'
className='password-input'
value={password?.password}
onChange={null}
readOnly={true}
/>
<button
onClick={onCopyClick}
className={
password?.status ? "copy-button copid" : "copy-button"
}
>
{password?.status ? "Copied" : "Copy"}
</button>
</div>
<div>
<button onClick={generateHander} className='generate'>
Generate Password
</button>
</div>
</section>
</div>
{/* Your Code Ends Here */}
</div>
</div>
);
}

const CheckBox = ({ name, checked, getCheckedItem, id }) => {
const checkboxChangeHandler = (id) => (e) => {
getCheckedItem(id, e.target.checked);
};

return (
<div className='checkbox-comp'>
<label htmlFor={name}>{name}</label>
<input
checked={checked}
className='checkbox'
onChange={checkboxChangeHandler(id)}
id={name}
type='checkbox'
/>
</div>
);
};

export default PasswordGenerator;
16 changes: 16 additions & 0 deletions src/plays/password-generator/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Password Generator
The `Password Generator` project is a fun project which shows the usecase of some concept in ReactJS.

- Multiple Checkbox Handling.
- Managing Complex logic to generate random password
- Use and manage multiple nested `useState` hooks
- Use of `useEffect` hook in ReactJS.
- Also how to copy text and handle error are shown.

# File Contents

For now all the necessary components, functions and logics are managed inside `PasswordGenerator.jsx` file.and the css are contained inside `password-generator-style.css`

also there is a `data.json` which is the main source and feeding requied data into the `PasswordGenerator.jsx` component.

Happy Learning!
5 changes: 5 additions & 0 deletions src/plays/password-generator/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"uppercase": ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"],
"numbers": ["0","1","2","3","4","5","6","7","8","9"],
"special": ["!","@","#","$","%","^","&","*","(",")","-","_","=","+","[","{","]","}","|",";",":","'","\"",",",".","<",">","/","?"]
}
Loading