aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/integer-base-converter/integer-base-converter.model.ts2
-rw-r--r--src/tools/integer-base-converter/integer-base-converter.vue49
-rw-r--r--src/utils/error.test.ts29
-rw-r--r--src/utils/error.ts24
4 files changed, 93 insertions, 11 deletions
diff --git a/src/tools/integer-base-converter/integer-base-converter.model.ts b/src/tools/integer-base-converter/integer-base-converter.model.ts
index c3ed66d..cfe15bd 100644
--- a/src/tools/integer-base-converter/integer-base-converter.model.ts
+++ b/src/tools/integer-base-converter/integer-base-converter.model.ts
@@ -7,7 +7,7 @@ export function convertBase({ value, fromBase, toBase }: { value: string; fromBa
.reverse()
.reduce((carry: number, digit: string, index: number) => {
if (!fromRange.includes(digit)) {
- throw new Error('Invalid digit `' + digit + '` for base ' + fromBase + '.');
+ throw new Error('Invalid digit "' + digit + '" for base ' + fromBase + '.');
}
return (carry += fromRange.indexOf(digit) * Math.pow(fromBase, index));
}, 0);
diff --git a/src/tools/integer-base-converter/integer-base-converter.vue b/src/tools/integer-base-converter/integer-base-converter.vue
index 04c4321..33b1dee 100644
--- a/src/tools/integer-base-converter/integer-base-converter.vue
+++ b/src/tools/integer-base-converter/integer-base-converter.vue
@@ -4,7 +4,7 @@
<div v-if="styleStore.isSmallScreen">
<n-input-group>
<n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label>
- <n-input-number v-model:value="inputNumber" min="0" style="width: 100%" />
+ <n-input v-model:value="input" style="width: 100%" :status="error ? 'error' : undefined" />
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label>
@@ -14,51 +14,65 @@
<n-input-group v-else>
<n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label>
- <n-input-number v-model:value="inputNumber" min="0" />
+ <n-input v-model:value="input" :status="error ? 'error' : undefined" />
<n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label>
<n-input-number v-model:value="inputBase" max="64" min="2" />
</n-input-group>
+
+ <n-alert v-if="error" style="margin-top: 25px" type="error">{{ error }}</n-alert>
<n-divider />
<n-input-group>
<n-input-group-label style="flex: 0 0 170px"> Binary (2): </n-input-group-label>
- <input-copyable :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 2 })" readonly />
+ <input-copyable
+ :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 2 })"
+ readonly
+ placeholder="Binary version will be here..."
+ />
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 170px"> Octal (8): </n-input-group-label>
- <input-copyable :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 8 })" readonly />
+ <input-copyable
+ :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 8 })"
+ readonly
+ placeholder="Octal version will be here..."
+ />
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 170px"> Decimal (10): </n-input-group-label>
<input-copyable
- :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 10 })"
+ :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 10 })"
readonly
+ placeholder="Decimal version will be here..."
/>
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 170px"> Hexadecimal (16): </n-input-group-label>
<input-copyable
- :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 16 })"
+ :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 16 })"
readonly
+ placeholder="Decimal version will be here..."
/>
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 170px"> Base64 (64): </n-input-group-label>
<input-copyable
- :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 64 })"
+ :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 64 })"
readonly
+ placeholder="Base64 version will be here..."
/>
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 85px"> Custom: </n-input-group-label>
<n-input-number v-model:value="outputBase" style="flex: 0 0 86px" max="64" min="2" />
<input-copyable
- :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: outputBase })"
+ :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: outputBase })"
readonly
+ :placeholder="`Base ${outputBase} will be here...`"
/>
</n-input-group>
</n-card>
@@ -66,16 +80,31 @@
</template>
<script setup lang="ts">
-import { ref } from 'vue';
+import { computed, ref } from 'vue';
import { useStyleStore } from '@/stores/style.store';
+import { getErrorMessageIfThrows } from '@/utils/error';
import { convertBase } from './integer-base-converter.model';
import InputCopyable from '../../components/InputCopyable.vue';
const styleStore = useStyleStore();
-const inputNumber = ref(42);
+const input = ref('42');
const inputBase = ref(10);
const outputBase = ref(42);
+
+function errorlessConvert(...args: Parameters<typeof convertBase>) {
+ try {
+ return convertBase(...args);
+ } catch (err) {
+ return '';
+ }
+}
+
+const error = computed(() =>
+ getErrorMessageIfThrows(() =>
+ convertBase({ value: input.value, fromBase: inputBase.value, toBase: outputBase.value }),
+ ),
+);
</script>
<style lang="less" scoped>
diff --git a/src/utils/error.test.ts b/src/utils/error.test.ts
new file mode 100644
index 0000000..0272804
--- /dev/null
+++ b/src/utils/error.test.ts
@@ -0,0 +1,29 @@
+import { describe, expect, it } from 'vitest';
+import { getErrorMessageIfThrows } from './error';
+
+describe('error util', () => {
+ describe('getErrorMessageIfThrows', () => {
+ it('get an error message if the callback throws, undefined instead', () => {
+ expect(
+ getErrorMessageIfThrows(() => {
+ throw 'message';
+ }),
+ ).to.equal('message');
+
+ expect(
+ getErrorMessageIfThrows(() => {
+ throw new Error('message');
+ }),
+ ).to.equal('message');
+
+ expect(
+ getErrorMessageIfThrows(() => {
+ throw { message: 'message' };
+ }),
+ ).to.equal('message');
+
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ expect(getErrorMessageIfThrows(() => {})).to.equal(undefined);
+ });
+ });
+});
diff --git a/src/utils/error.ts b/src/utils/error.ts
new file mode 100644
index 0000000..681db91
--- /dev/null
+++ b/src/utils/error.ts
@@ -0,0 +1,24 @@
+import _ from 'lodash';
+
+export { getErrorMessageIfThrows };
+
+function getErrorMessageIfThrows(cb: () => unknown) {
+ try {
+ cb();
+ return undefined;
+ } catch (err) {
+ if (_.isString(err)) {
+ return err;
+ }
+
+ if (_.isError(err)) {
+ return err.message;
+ }
+
+ if (_.isObject(err) && _.has(err, 'message')) {
+ return (err as { message: string }).message;
+ }
+
+ return 'An error as occurred.';
+ }
+}