Open In App

Build a Password Manager using React

Last Updated : 15 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Password manager using React js provides a secure and user-frie­ndly environment for users to store­ and manage their crede­ntials. It offers convenient fe­atures like adding, editing, and de­leting password entries. The user can show/hide their password by clicking on a particular button.

Preview of final output: Let us have a look at how the final application will look like:

gfg

Prerequisites and Technologies Used:

Approach to create the Password Manager:

  • The compone­nt’s state is initialized by the constructor with value­s such as website, username­, password, passwords array, and various flags.
  • After the­ component is mounted, the “compone­ntDidMount” function triggers the exe­cution of “showPasswords()”. This action effectively re­sets the formand editing mode.
  • The compone­nt’s structure is defined in the­ rendering process, which involve­s handling password entries, alerts, and input fie­lds. Additionally, its behavior is adjusted to accommodate the­ addition or editing of entries.

Functionalities to create the Password Manager:

  • maskPassword: Masks the password with asterisks (‘*’).
  • copyPassword: Asynchronously copies a password to the clipboard.
  • deletePassword: Deletes a password entry and shows a success alert.
  • showPasswords: Resets the component’s state, clearing the form and editing mode.
  • savePassword: Adds or updates password entries based on user input.
  • editPassword: Allows editing of existing password entries.
  • renderPasswordList: Generates HTML elements for displaying password entries.

Steps to Create the Password Manager :

Step 1: Create a react application by using this command

npx create-react-app  password-manager-app

Step 2: After creating your project folder, i.e. password-manager-app, use the following command to navigate to it:

cd password-manager-app

Project Structure:

The updated dependencies in package.json file will look like:

"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"react-icons": "^4.11.0"
"web-vitals": "^2.1.4"
}

Example: Write the below code in App.js file and App.css in the src directory

Javascript




import React, { Component } from 'react';
import './App.css';
import { FaCopy, FaEdit, FaTrash } from 'react-icons/fa';
  
class App extends Component {
  // Constructor to initialize the component's state
  constructor(props) {
    super(props);
  
    this.state = {
      website: '',
      username: '',
      password: '',
      passwords: [],
      alertVisible: false,
      editing: false,
      editIndex: null,
      showPassword: false,
    };
  }
  
  componentDidMount() {
    this.showPasswords();
  }
  
  // Function to copy a password to the clipboard
  copyPassword = async (pass) => {
    try {
      const textArea = document.createElement('textarea');
      textArea.value = pass;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand('copy');
      document.body.removeChild(textArea);
      this.setState({ alertVisible: true });
      setTimeout(() => {
        this.setState({ alertVisible: false });
      }, 2000);
    } catch (error) {
      console.error('Error copying text:', error);
    }
  };
  
  // Function to delete a password entry
  deletePassword = (website) => {
    const updatedPasswords = this.state.passwords.filter(
      (e) => e.website !== website
    );
    this.setState({ passwords: updatedPasswords });
    alert(`Successfully deleted ${website}'s password`);
  };
  
  // Function to clear the form and reset editing mode
  showPasswords = () => {
    this.setState({
      passwords: [],
      website: '',
      username: '',
      password: '',
      editing: false,
      editIndex: null,
      showPassword: false,
    });
  };
  
  savePassword = () => {
    const { website, username, password, editing, editIndex, passwords } =
      this.state;
  
    if (!website || !username || !password) {
      alert('Please fill in all fields.');
      return;
    }
  
    if (editing && editIndex !== null) {
      // Replace the old entry with the updated one
      const updatedPasswords = [...passwords];
      updatedPasswords[editIndex] = {
        website,
        username,
        password,
      };
      this.setState({
        passwords: updatedPasswords,
        editing: false,
        editIndex: null,
        website: '',
        username: '',
        password: '',
      });
    } else {
      const newPassword = {
        website,
        username,
        password,
      };
      this.setState((prevState) => ({
        // Add the new entry to passwords array
        passwords: [...prevState.passwords, newPassword],
        website: '',
        username: '',
        password: '',
      }));
    }
  };
  
  // Function to edit a password entry
  editPassword = (index) => {
    const { passwords } = this.state;
    this.setState({
      editing: true,
      editIndex: index,
      website: passwords[index].website,
      username: passwords[index].username,
      password: passwords[index].password,
    });
  };
  
  // Function to toggle password visibility
  togglePasswordVisibility = () => {
    this.setState((prevState) => ({
      showPassword: !prevState.showPassword,
    }));
  };
  
  renderPasswordList = () => {
    const { passwords, showPassword } = this.state;
  
    return passwords.map((item, index) => (
      <div className="passwordItem" key={index}>
        <div className="listItem">
          <div className="listLabel">Website:</div>
          <div className="listValue">{item.website}</div>
          <div className="listLabel">Username:</div>
          <div className="listValue">{item.username}</div>
          <div className="listLabel">Password:</div>
          <div className="listValue">
            <span className="passwordField">
              {showPassword ? item.password : item.password.replace(/./g, '*')}
            </span>
          </div>
          <div className="passwordButtons">
            <button
              className="showPasswordButton"
              onClick={this.togglePasswordVisibility}
            >
              {showPassword ? 'Hide' : 'Show'}
            </button>
          </div>
          <div className="iconContainer">
            <div
              className="icon"
              onClick={() => this.copyPassword(item.password)}
            >
              <FaCopy size={20} color="#555" />
            </div>
            <div className="icon" onClick={() => this.editPassword(index)}>
              <FaEdit size={20} color="#555" />
            </div>
            <div
              className="icon"
              onClick={() => this.deletePassword(item.website)}
            >
              <FaTrash size={20} color="#555" />
            </div>
          </div>
        </div>
      </div>
    ));
  };
  
  render() {
    const { website, username, password, editing } = this.state;
  
    return (
      <div className="container">
        <div className="content">
          <h1 className="heading">Password Manager</h1>
          <h2 className="subHeading">
            Your Passwords
            {this.state.alertVisible && <span id="alert">(Copied!)</span>}
          </h2>
          {this.state.passwords.length === 0 ? (
            <p className="noData">No Data To Show</p>
          ) : (
            <div className="table">{this.renderPasswordList()}</div>
          )}
  
          <h2 className="subHeading">
            {editing ? 'Edit Password' : 'Add a Password'}
          </h2>
          <input
            className="input"
            placeholder="Website"
            value={website}
            onChange={(e) => this.setState({ website: e.target.value })}
          />
          <input
            className="input"
            placeholder="Username"
            value={username}
            onChange={(e) => this.setState({ username: e.target.value })}
          />
          <input
            className="input"
            placeholder="Password"
            type="password"
            value={password}
            onChange={(e) => this.setState({ password: e.target.value })}
          />
          <div className="submitButton" onClick={this.savePassword}>
            <span className="submitButtonText">
              {editing ? 'Update Password' : 'Add Password'}
            </span>
          </div>
        </div>
      </div>
    );
  }
}
  
export default App;


CSS




body {
  background-color: #f0f0f0;
  font-family: 'Arial', sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}
  
.container {
  width: 100%;
  text-align: center;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  padding: 20px;
}
  
.heading {
  font-size: 28px;
  margin-bottom: 20px;
  color: #333;
}
  
.subHeading {
  font-size: 20px;
  margin-bottom: 15px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
  
#alert {
  color: green;
  margin-left: 5px;
}
  
.input {
  width: 90%;
  padding: 12px;
  border: 2px solid #ccc;
  border-radius: 5px;
  margin: 10px 0;
  font-size: 16px;
}
  
.table {
  margin: 2rem 0;
}
  
.passwordItem {
  background-color: #f9f9f9;
  border: 1px solid #ccc;
  border-radius: 10px;
  padding: 15px;
  margin-bottom: 15px;
}
  
.listItem {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
  margin-right: 10px;
}
.listValue {
  margin-right: 15px;
}
.listLabel {
  font-weight: bold;
  width: 100px;
  padding: 12px;
  font-size: 18px;
}
  
.showPasswordIcon {
  cursor: pointer;
  margin-left: 16px;
  color: #007bff;
  font-size: 20px;
  transition: color 0.3s;
}
  
.showPasswordIcon:hover {
  color: #0056b3;
}
  
.copyIcon,
editIcon,
deleteIcon {
  cursor: pointer;
  color: #555;
  font-size: 20px;
  transition: color 0.3s;
  margin-left: 10px;
}
  
.copyIcon:hover,
editIcon:hover,
deleteIcon:hover {
  color: #007bff;
}
  
.submitButton {
  background: #007bff;
  color: #fff;
  padding: 12px 24px;
  text-align: center;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  margin: 12px 0;
  font-weight: bold;
  font-size: 18px;
}
  
.noData {
  text-align: center;
  color: #777;
  margin-top: 20px;
  font-size: 18px;
}


Steps to run the Application:

Step 1: Type the following command in the terminal:

npm start

Step 2: Type the following URL in the browser:

 http://localhost:3000/

Output:gfg



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads