DEV Community

Gustavo Tavares
Gustavo Tavares

Posted on

Time It App Lets Go!

Hey,

It’s good to see you again!

This time I want to talk about my Second time collaborating on someone’s project. This time I was able to collaborate in the Time It App.
TimeItAppLogo

Time It app goal is to allow its users to record time and calculate the amount they should charge for it. It keeps the record of all the timed events you have and allow you to copy it to your clipboard.


The Issue

Issue #2 was the issue I decided to work on. Basically, my goal was to add a button loader for the Settings page buttons.
The project use React to build its components so, besides my React being rusted, it was really good to work with it again.


The Solution

First, I had to make a loader using CSS. I used this as reference and ended up using this:


.loader {
    border: 10px solid #f3f3f3;
    border-radius: 50%;
    border-top: 10px solid #364f6b;
    width: 15px;
    height: 15px;
    -webkit-animation: spin 2s linear infinite; /* Safari */
    animation: spin 1.5s linear infinite;
    margin: auto;
  }

  /* Safari */
  @-webkit-keyframes spin {
    0% { -webkit-transform: rotate(0deg); }
    100% { -webkit-transform: rotate(360deg); }
  }

  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
Enter fullscreen mode Exit fullscreen mode

To make the Loaders work, I added a state for each, L8 and L9.

const [isLoadingDelete, setIsLoadingDelete] = useState(false);
const [isLoadingCopy, setIsLoadingCopy] = useState(false);
Enter fullscreen mode Exit fullscreen mode

Because I had to make a loader appear for a process that is almost instantly, I thought it was a better idea to make a symbolic loader instead of one that would last until the process were being processed.

So I decided to use setTimeout() to make the loader appear for just a couple of seconds.

 function clearLocalStorageData() {
        localStorage.clear();
        setIsLocalStorageEmpty(true);
        if(!isLocalStorageEmpty){ // This one!
         setTimeout(function(){ setIsLoadingDelete(false); }, 1500); // This one!
         setIsLoadingDelete(true); // This one!
        }
    }
Enter fullscreen mode Exit fullscreen mode

and

function localStorageTextToClipboard(text) {
        if (text != null) {
            let newText = text.toString();
            // formatting copied output
            newText = replaceAll(text, '[{', '');
            newText = replaceAll(newText, '}]', '');
            newText = replaceAll(newText, '{', '\n');
            newText = replaceAll(newText, '}', '');
            newText = replaceAll(newText, ',', '\n');
            const temp = document.createElement('textarea');
            document.body.appendChild(temp);
            temp.value = newText;
            temp.select();
            document.execCommand('copy');
            document.body.removeChild(temp);
            setTimeout(function(){ setIsLoadingCopy(false); }, 1500); // This one!
            setIsLoadingCopy(true); // This one!
        } 
    }
Enter fullscreen mode Exit fullscreen mode

Then I just had to adjust the JSX to make it work:

 {isLoadingDelete 
    ? <div className="loader" /> 
    : <button
     className={`${isLocalStorageEmpty
     ? 'GreyButtonBlueText'
     : 'PinkButtonYellowText'
  }`}
     onClick={clearLocalStorageData}
  >
   delete tasks
 </button>}
Enter fullscreen mode Exit fullscreen mode

and

 {isLoadingCopy 
   ? <div className="loader" /> 
   : <button
    className="PinkButtonYellowText"
     onClick={ () => 
     localStorageTextToClipboard(localStorage.getItem('tasks'))}
     >
      copy task data
   </button>}

Enter fullscreen mode Exit fullscreen mode

I also happened to find a bug that made the onClick function to fire nonstop if a task could be copied to the clipboard, which I fixed while was solving the loader question.

 //Before 
onClick={localStorageTextToClipboard(localStorage.getItem('tasks'))}

//Fixed
onClick={ () =>
  localStorageTextToClipboard(localStorage.getItem('tasks'))}
Enter fullscreen mode Exit fullscreen mode

The Result

Before:
Gif 1

After:
Gif 2


Finally

This was a great project to contribute to, the people that I have interacted were polite and very welcoming which made me feel very comfortable.
Feels really good to be useful and capable to help other people.

I hope you have enjoyed reading this!
Thank you so much and see you again!

Discussion (0)