aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-04-14 18:18:15 +0200
committerGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-04-14 18:18:15 +0200
commit5582d75927b560d9259929c787c0809634d1f8ae (patch)
treea8dcd4137fbf968ed1ced0aec577cfc40ae0e50d /src
parent203b6a9d73dcb30182b130de59920534e18b76b4 (diff)
downloadit-tools-5582d75927b560d9259929c787c0809634d1f8ae.tar.gz
it-tools-5582d75927b560d9259929c787c0809634d1f8ae.tar.zst
it-tools-5582d75927b560d9259929c787c0809634d1f8ae.zip
feat(tool): qr-code generator
Diffstat (limited to 'src')
-rw-r--r--src/composable/downloadBase64.ts12
-rw-r--r--src/plugins/naive.plugin.ts2
-rw-r--r--src/tools/index.ts3
-rw-r--r--src/tools/qr-code-generator/index.ts11
-rw-r--r--src/tools/qr-code-generator/qr-code-generator.vue60
-rw-r--r--src/tools/qr-code-generator/useQRCode.ts35
6 files changed, 122 insertions, 1 deletions
diff --git a/src/composable/downloadBase64.ts b/src/composable/downloadBase64.ts
new file mode 100644
index 0000000..e5b621f
--- /dev/null
+++ b/src/composable/downloadBase64.ts
@@ -0,0 +1,12 @@
+import type { Ref } from 'vue';
+
+export function useDownloadFileFromBase64({ source, filename = 'file' }: { source: Ref<string>; filename?: string }) {
+ return {
+ download() {
+ const a = document.createElement('a');
+ a.href = source.value;
+ a.download = filename;
+ a.click();
+ },
+ };
+}
diff --git a/src/plugins/naive.plugin.ts b/src/plugins/naive.plugin.ts
index 0896e51..ccbb049 100644
--- a/src/plugins/naive.plugin.ts
+++ b/src/plugins/naive.plugin.ts
@@ -47,9 +47,11 @@ import {
NStatistic,
NTable,
NUploadDragger,
+ NImage,
} from 'naive-ui';
const components = [
+ NImage,
NUploadDragger,
NTable,
NStatistic,
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 86116c6..577c1b4 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -1,6 +1,7 @@
import { LockOpen } from '@vicons/tabler';
import type { ToolCategory } from './Tool';
+import { tool as qrCodeGenerator } from './qr-code-generator';
import { tool as base64Converter } from './base64-converter';
import { tool as crontabGenerator } from './crontab-generator';
import { tool as textStatistics } from './text-statistics';
@@ -31,7 +32,7 @@ export const toolsByCategory: ToolCategory[] = [
{
name: 'Web',
icon: LockOpen,
- components: [urlEncoder],
+ components: [urlEncoder, qrCodeGenerator],
},
{
name: 'Development',
diff --git a/src/tools/qr-code-generator/index.ts b/src/tools/qr-code-generator/index.ts
new file mode 100644
index 0000000..70e86dc
--- /dev/null
+++ b/src/tools/qr-code-generator/index.ts
@@ -0,0 +1,11 @@
+import { Qrcode } from '@vicons/tabler';
+import type { ITool } from './../Tool';
+
+export const tool: ITool = {
+ name: 'QR Code generator',
+ path: '/qr-code-generator',
+ description: 'Generate and download QR-code for an url or just a text and customize the background and foreground colors.',
+ keywords: ['qr', 'code', 'generator', 'square', 'color', 'link', 'low', 'medium', 'quartile', 'high', 'transparent'],
+ component: () => import('./qr-code-generator.vue'),
+ icon: Qrcode,
+};
diff --git a/src/tools/qr-code-generator/qr-code-generator.vue b/src/tools/qr-code-generator/qr-code-generator.vue
new file mode 100644
index 0000000..e23f00a
--- /dev/null
+++ b/src/tools/qr-code-generator/qr-code-generator.vue
@@ -0,0 +1,60 @@
+<template>
+ <n-card>
+ <n-grid cols="3" x-gap="12">
+ <n-gi span="2">
+ <n-form label-width="130" label-placement="left">
+ <n-form-item label="Text:">
+ <n-input v-model:value="text" placeholder="Your link or text..." />
+ </n-form-item>
+ <n-form-item label="Foreground color:">
+ <n-color-picker v-model:value="foreground" :modes="['hex']" />
+ </n-form-item>
+ <n-form-item label="Background color:">
+ <n-color-picker v-model:value="background" :modes="['hex']" />
+ </n-form-item>
+ <n-form-item label="Error resistance:">
+ <n-select v-model:value="errorCorrectionLevel"
+ :options="errorCorrectionLevels.map((value) => ({ label: value, value }))" />
+ </n-form-item>
+ </n-form>
+ </n-gi>
+ <n-gi>
+ <n-space justify="center" align="center" vertical>
+ <n-image :src="qrcode" width="200" />
+ <n-button @click="download" secondary>Download qr-code</n-button>
+ </n-space>
+ </n-gi>
+ </n-grid>
+ </n-card>
+</template>
+
+<script setup lang="ts">
+import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
+import { useQRCode } from './useQRCode'
+import { ref } from 'vue';
+import type { QRCodeErrorCorrectionLevel } from 'qrcode';
+
+
+const foreground = ref('#000000ff')
+const background = ref('#ffffffff')
+const errorCorrectionLevel = ref<QRCodeErrorCorrectionLevel>('medium')
+
+const errorCorrectionLevels = ['low', 'medium', 'quartile', 'high']
+
+const text = ref('https://it-tools.tech')
+const { qrcode } = useQRCode({
+ text,
+ color: {
+ background,
+ foreground
+ },
+ errorCorrectionLevel,
+ options: { width: 1024 }
+})
+
+const { download } = useDownloadFileFromBase64({ source: qrcode, filename: 'qr-code.png' })
+
+</script>
+
+<style lang="less" scoped>
+</style> \ No newline at end of file
diff --git a/src/tools/qr-code-generator/useQRCode.ts b/src/tools/qr-code-generator/useQRCode.ts
new file mode 100644
index 0000000..c706d0d
--- /dev/null
+++ b/src/tools/qr-code-generator/useQRCode.ts
@@ -0,0 +1,35 @@
+import QRCode, { type QRCodeErrorCorrectionLevel, type QRCodeToDataURLOptions } from 'qrcode';
+import { ref, watch, type Ref } from 'vue';
+
+export function useQRCode({
+ text,
+ color: { background, foreground },
+ errorCorrectionLevel,
+ options,
+}: {
+ text: Ref<string>;
+ color: { foreground: Ref<string>; background: Ref<string> };
+ errorCorrectionLevel: Ref<QRCodeErrorCorrectionLevel>;
+ options?: QRCodeToDataURLOptions;
+}) {
+ const qrcode = ref('');
+
+ watch(
+ [text, background, foreground, errorCorrectionLevel],
+ async () => {
+ if (text.value)
+ qrcode.value = await QRCode.toDataURL(text.value, {
+ color: {
+ dark: foreground.value,
+ light: background.value,
+ ...options?.color,
+ },
+ errorCorrectionLevel: errorCorrectionLevel.value,
+ ...options,
+ });
+ },
+ { immediate: true }
+ );
+
+ return { qrcode };
+}