Hello, first post on DEV for this professional account, it will be written in English and French to facilitate reading.

## Why I created that?

I'm a **freelancer** since april 2023, I **invoice by the hour according to my tasks**. So I used a classic website or even a calculator to get my result for each task. Except it was taking me a bit longer, and I was thinking it **could be an even simpler and faster process**.

So, as a web developer, I **designed this web interface to meet my needs**. **It's accessible to everyone, and free**. The magic of the Internet.

## What is a cross-multiplication?

In mathematics, specifically in elementary arithmetic and elementary algebra, given an equation between two fractions or rational expressions, one can cross-multiply to simplify the equation or determine the value of a variable.

That's all. Thanks Wikipedia. ๐

In mathematics, specifically in elementary arithmetic and elementary algebra, given an equation between two fractions or rational expressions, one can **cross-multiply** to simplify the equation or determine the value of a variable.

## How I created this tool?

The website is under **Nuxt**, I use SASS for styling.

The script is quite simple, written in two parts, one to calculate the total, and the second to transform "*4h23*" into "*263m*".

### How I store datas?

All data is stored via *localStorage*, based on your client. This makes it easier to have both values (time and price) saved when you return to the page.

```
watch([defaultMinutes, defaultHourlyRate, defaultTimePerMinutes, result], () => {
localStorage.setItem('defaultMinutes', defaultMinutes.value);
localStorage.setItem('defaultHourlyRate', defaultHourlyRate.value);
});
onMounted(() => {
if (localStorage.getItem('defaultMinutes')) {
defaultMinutes.value = localStorage.getItem('defaultMinutes');
}
if (localStorage.getItem('defaultHourlyRate')) {
defaultHourlyRate.value = localStorage.getItem('defaultHourlyRate');
}
});
```

When the page is loaded (onMounted), we retrieve the localstorage if available to set them to the correct values. Nothing mysterious! ๐งโโ๏ธ

### Converting hours into minutes

Okay, this part takes a bit longer to explain, but if you understand a bit of code logic, you'll notice quite easily how I do it.

First I simply check if defaultTimePerMinutes is not undefined, then other conditions to avoid errors, and then we check if there's the letter "h" to split the two parts.

We calculate the hours value, i.e. the value to the left of "h" in minutes, and add the two parts to obtain a total in minutes.

```
watch([defaultMinutes, defaultHourlyRate, defaultTimePerMinutes], () => {
if (!defaultTimePerMinutes.value) {
result.value = null;
return;
}
if (isNaN(defaultTimePerMinutes.value) && !defaultTimePerMinutes.value.includes('h')) {
result.value = null;
totalMinutes.value = null;
return;
}
// if defaultTimePerMinutes contains a value of type "1h30".
if (defaultTimePerMinutes.value.includes('h')) {
let [hours, minutes] = defaultTimePerMinutes.value.split('h');
minutes = minutes ? parseInt(minutes) : 0;
let totalHours = hours * 60;
totalMinutes.value = totalHours + minutes;
result.value = (totalMinutes.value * defaultHourlyRate.value) / defaultMinutes.value;
result.value = result.value.toFixed(2);
} else {
totalMinutes.value = defaultTimePerMinutes.value;
result.value = (totalMinutes.value * defaultHourlyRate.value) / defaultMinutes.value;
result.value = result.value.toFixed(2);
}
if (totalMinutes.value === 0 || !totalMinutes) {
totalMinutes.value = null;
}
});
```

Don't hesitate to give me feedback, or even a tool like this one, which can be great to set up for calculations in a professional environment. It's always interesting to know what's missing on the Internet!

## Top comments (0)