Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(new-tool):-currency-converter #54

Merged
merged 11 commits into from
Nov 4, 2024
3 changes: 2 additions & 1 deletion .eslintrc-auto-import.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"WritableComputedRef": true
"WritableComputedRef": true,
"useClipboardItems": true
}
}
2 changes: 2 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ declare module '@vue/runtime-core' {
CTooltip: typeof import('./src/ui/c-tooltip/c-tooltip.vue')['default']
'CTooltip.demo': typeof import('./src/ui/c-tooltip/c-tooltip.demo.vue')['default']
CurlConverter: typeof import('./src/tools/curl-converter/curl-converter.vue')['default']
CurrencyConverter: typeof import('./src/tools/currency-converter/currency-converter.vue')['default']
DateTimeConverter: typeof import('./src/tools/date-time-converter/date-time-converter.vue')['default']
'DemoHome.page': typeof import('./src/ui/demo/demo-home.page.vue')['default']
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
Expand Down Expand Up @@ -148,6 +149,7 @@ declare module '@vue/runtime-core' {
JsUnobfuscator: typeof import('./src/tools/js-unobfuscator/js-unobfuscator.vue')['default']
JwtParser: typeof import('./src/tools/jwt-parser/jwt-parser.vue')['default']
KeycodeInfo: typeof import('./src/tools/keycode-info/keycode-info.vue')['default']
ListComparer: typeof import('./src/tools/list-comparer/list-comparer.vue')['default']
ListConverter: typeof import('./src/tools/list-converter/list-converter.vue')['default']
LiveCode: typeof import('./src/tools/live-code/live-code.vue')['default']
LocaleSelector: typeof import('./src/modules/i18n/components/locale-selector.vue')['default']
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@tiptap/pm": "2.1.6",
"@tiptap/starter-kit": "2.1.6",
"@tiptap/vue-3": "2.0.3",
"@types/arr-diff": "^4.0.3",
"@types/figlet": "^1.5.8",
"@types/markdown-it": "^13.0.7",
"@types/memorystream": "^0.3.4",
Expand All @@ -54,6 +55,7 @@
"@vueuse/core": "^10.11.1",
"@vueuse/head": "^1.0.0",
"@vueuse/router": "^10.0.0",
"arr-diff": "^4.0.0",
"bcryptjs": "^2.4.3",
"change-case": "^4.1.2",
"cidr-tools": "^7.0.4",
Expand All @@ -65,6 +67,8 @@
"cronstrue": "^2.26.0",
"crypto-js": "^4.1.1",
"curlconverter": "^4.10.1",
"currency-codes-ts": "^3.0.0",
"currency-exchanger-js": "^1.0.4",
"date-fns": "^2.29.3",
"decomposerize": "^1.4.1",
"dns-query": "^0.11.2",
Expand All @@ -74,6 +78,7 @@
"exif-be-gone": "^1.5.1",
"exifreader": "^4.20.0",
"fflate": "^0.8.2",
"fast_array_intersect": "^1.1.0",
"figlet": "^1.7.0",
"figue": "^1.2.0",
"fuse.js": "^6.6.2",
Expand Down
57 changes: 57 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

119 changes: 119 additions & 0 deletions src/tools/currency-converter/currency-converter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<script setup lang="ts">
import { code, countries, country } from 'currency-codes-ts';
import converter from 'currency-exchanger-js';
import moneysData from './moneys.json';
import { useQueryParamOrStorage } from '@/composable/queryParams';

const allCurrencies = Object.entries(moneysData).map(([k, v]) => ({ value: k, label: v || k }));
const otherCurrencies = useQueryParamOrStorage<{ name: string }[]>({ name: 'to', storageName: 'currency-conv:others', defaultValue: [{ name: 'usd' }] });
const currentCurrency = useQueryParamOrStorage<string>({ name: 'from', storageName: 'currency-conv:cur', defaultValue: 'eur' });
const amount = ref(1);
const currentDatetime = ref(Date.now());

const convertedCurrencies = computedAsync<Record<string, number>>(async () => {
const currentCurrencyValue = currentCurrency.value;
const currentDatetimeValue = currentDatetime.value;
const amountValue = amount.value;
const otherCurrenciesValues = otherCurrencies.value;

let result = {};
for (const targetCurrency of otherCurrenciesValues) {
const value = await converter.convertOnDate(amountValue, currentCurrencyValue, targetCurrency.name, new Date(currentDatetimeValue));
result = { ...result, [targetCurrency.name]: value };
}
return result;
});

const countryToCurrenciesInput = ref('France');
const allCountries = countries();
const countryToCurrenciesOutput = computed(() => country(countryToCurrenciesInput.value));

const currencyToCountriesInput = ref('eur');
const currencyToCountriesOutput = computed(() => code(currencyToCountriesInput.value));
</script>

<template>
<div>
<c-card title="Currency Converter" mb-2>
<c-select
v-model:value="currentCurrency"
label="From"
label-position="left"
searchable
:options="allCurrencies"
mb-2
/>
<n-form-item label="Amount:" label-placement="left" mb-2>
<n-input-number v-model:value="amount" :min="0" />
</n-form-item>

<n-form-item label="For Date:" label-placement="left" mb-2>
<n-date-picker
v-model:value="currentDatetime"
type="date"
/>
</n-form-item>

<c-card title="Converted currencies">
<n-dynamic-input
v-model:value="otherCurrencies"
show-sort-button
:on-create="() => ({ name: 'eur' })"
>
<template #default="{ value }">
<div flex flex-wrap items-center gap-1>
<n-select
v-model:value="value.name"
filterable
placeholder="Please select a currency"
:options="allCurrencies"
w-full
/>
<input-copyable readonly :value="convertedCurrencies ? convertedCurrencies[value.name] : 0" />
</div>
</template>
</n-dynamic-input>
</c-card>
</c-card>

<c-card title="Country to Currencies" mb-2>
<c-select
v-model:value="countryToCurrenciesInput"
label="Country"
label-position="left"
searchable
:options="allCountries"
/>

<n-divider />

<ul>
<li v-for="(currency, ix) in countryToCurrenciesOutput" :key="ix">
{{ currency.currency }} [{{ currency.code }}/{{ currency.number }} - {{ currency.digits }}digits] (also in: {{ currency.countries?.join(', ') }})
</li>
</ul>
</c-card>

<c-card title="Currencies to Countries" mb-2>
<c-select
v-model:value="currencyToCountriesInput"
label="Currency"
label-position="left"
searchable
:options="allCurrencies"
/>

<n-divider />

<n-p v-if="currencyToCountriesOutput">
{{ currencyToCountriesOutput.currency }} [{{ currencyToCountriesOutput.code }}/{{ currencyToCountriesOutput.number }} - {{ currencyToCountriesOutput.digits }}digits]
</n-p>

<ul v-if="currencyToCountriesOutput">
<li v-for="(countryName, ix) in currencyToCountriesOutput.countries" :key="ix">
{{ countryName }}
</li>
</ul>
</c-card>
</div>
</template>
4 changes: 4 additions & 0 deletions src/tools/currency-converter/currency-exchanger-js.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module 'currency-exchanger-js'{
export function convertOnDate(value: number,fromCurrency: string,toCurrency: string,inputDate: Date): number;
export function convert(value: number,fromCurrency: string,toCurrency: string): number;
}
12 changes: 12 additions & 0 deletions src/tools/currency-converter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Currency } from '@vicons/tabler';
import { defineTool } from '../tool';

export const tool = defineTool({
name: 'Currency Converter',
path: '/currency-converter',
description: 'Convert currency values using ExchangeRate-API',
keywords: ['currency', 'converter'],
component: () => import('./currency-converter.vue'),
icon: Currency,
createdAt: new Date('2024-08-15'),
});
Loading
Loading