Skip to content

ajsaule/password-generator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

467ddc5 · Oct 22, 2022

History

31 Commits
Oct 12, 2022
Oct 12, 2022
Oct 4, 2022
Oct 10, 2022
Oct 2, 2022
Oct 4, 2022
Oct 22, 2022
Oct 12, 2022
Oct 4, 2022
Oct 12, 2022

Repository files navigation

Password generator

Table of contents

Overview

The challenge

Users should be able to:

  • Generate a password based on the selected inclusion options
  • Copy the generated password to the computer's clipboard
  • See a strength rating for their generated password
  • View the optimal layout for the interface depending on their device's screen size
  • See hover and focus states for all interactive elements on the page

Screenshot

Password Generator Screenshot

Links

My process

I first decided to break down the design with some planning using Excalidraw which I will attach some screenshots to display my planning process, I broke down into sections that allowed me to better understand what needed to be built in the end.

Excalidraw Screenshot

Built with

  • Semantic HTML5 markup
  • SASS (SCSS) - Syntactically Awesome Style Sheets
  • Flexbox
  • Mobile-first workflow
  • React - JS library
  • TypeScript

What I learned

Firstly that you can use Math.random() and multiply it by the length of an array to generate a randomly selected array index. Also I learned that you can create an array with with the array constructor and map over that passing a function reference to that map method to execute and return a 1:1 copy of that array but with the output of the given function that was passed to the method. The relevant code is below.

const characterGenerator = (): string => {
  const finalArray = characterFactory(
    upperCaseChecked,
    lowerCaseChecked,
    numbersChecked,
    symbolsChecked
  );
  return finalArray[Math.floor(Math.random() * finalArray.length)];
};

const wordGenerator = () => {
  return memorableList[Math.floor(Math.random() * memorableList.length)];
};

const passwordGenerator = (pwdLength: Number): string => {
  if (pwdLength >= 7) {
    const passwordString = [...Array(parseInt(pwdLength))]
      .map(characterGenerator)
      .join('');
    return passwordString;
  } else {
    const passwordString = [...Array(parseInt(pwdLength))]
      .map(wordGenerator)
      .join(passwordDelimiter);
    return passwordString;
  }
};

Another interesting insight was using the use-debounce package, that was a hook coming from the community that allowed me to delay a function from running again for a certain period of time, I was using this with a useEffect that was listening for window re-size changes, it helped significantly. One more thing I learned here is that clean up functions in useEffect hooks help with reducing memory leaks and unwanted behavior of apps.

const handleWindowResize = useDebouncedCallback((): void => {
  setWindowSize(getWindowSize());
}, 1000);

useEffect(() => {
  window.addEventListener('resize', handleWindowResize);

  return () => {
    window.removeEventListener('resize', handleWindowResize);
  };
});

Other learnings from this project would be that you can set the background linear-gradient() to apply a progressive fill based on some JS variables you pass interpolate into the string that is passed to the inline style on a HTML element:

  1. Firstly calculating the percentage for how much of the background the fill will be taking up (I needed to use // prettier-ignore here to set some custom brackets in the code)
// prettier-ignore
const sliderBackgroundPercentage =
  wordsChecked && windowSize.innerWidth > 768
    ? `${Math.round(((passwordLength - 1) / (6 - 1)) * 100)}%`
    : wordsChecked && windowSize.innerWidth <= 768
    ? `${Math.round(((passwordLength - 1) / (6 - 1)) * 100)}%`
    : windowSize.innerWidth > 768
    ? `${Math.round(((passwordLength - 7) / (35 - 7)) * 100)}%`
    : `${Math.round(((passwordLength - 7) / (25 - 7)) * 100)}%`;
  1. Then assigning the inline style the background property with the interpolated sting of percentages so they can dynamically shift when the slider is moved across the progress bar
<input style={{ background: `linear-gradient(to right, #a4ffaf
${sliderBackgroundPercentage}, #18171F ${sliderBackgroundPercentage}`, }} ... />

Lastly from this project would be using the resets on different browsers and targeting elements of the out of the box HTML5 tags such as <input/>.

input[type='range']::-moz-range-track,
input[type='range']::-ms-track,
input[type='range']::-webkit-slider-runnable-track {
  -ms-appearance: none;
  -moz-appearance: none;
  -webkit-appearance: none;
  border-radius: 0;
  height: 8px;
}

Continued development of this project

Things I would like to implement on this project:

  • An input field so the user can input their custom password and check how long it would take for it to be cracked
  • A checkbox to select camel case, snake case, pascal case and kebab case is already implemented
  • A tooltip when you hover over the time to crack field

Useful resources

  • Reactiflux Discord - This discord is amazing when you get stuck and can't find much help on the internet or SO
  • Stack overflow - Helped me to get unstuck at various phases.

Author

Acknowledgments

Big thanks to the devs from Reactiflux Discord that helped me when I got stuck along the way. I learned a lot from all of you, thanks for your volunteered time and patience you had with me.

Thanks to @cbserra for providing a redesign for my whole app UI aligning it more toward the previous design that was first given in the figma file. His design can be seen here - https://codepen.io/cbserra/pen/RwyqpVW. I will at some stage redesign the whole app to make it look in line with his design.

About

Password generator with a hash calculator included

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages