add frontend format support for currencies, add currencies endpoint

This commit is contained in:
Gregor Vostrak
2025-05-08 17:25:36 +02:00
parent 8b950d99d6
commit ed32c6b217
24 changed files with 352 additions and 128 deletions

View File

@@ -1,11 +1,9 @@
<script setup lang="ts">
import TextInput from '@/packages/ui/src/Input/TextInput.vue';
import {
formatCents,
getOrganizationCurrencySymbol,
} from '@/packages/ui/src/utils/money';
import { ref, watch } from 'vue';
import { formatCents } from '@/packages/ui/src/utils/money';
import { ref, watch, inject, type ComputedRef } from 'vue';
import { useFocus } from '@vueuse/core';
import type { Organization } from '@/packages/api/src';
const props = defineProps<{
name: string;
@@ -13,6 +11,8 @@ const props = defineProps<{
currency: string;
}>();
const organization = inject<ComputedRef<Organization>>('organization');
const model = defineModel<number | null>({
default: null,
});
@@ -58,9 +58,15 @@ function updateRate(value: string) {
}
function formatValue(modelValue: number | null) {
const formattedValue = formatCents(modelValue ?? 0, props.currency);
const formattedValue = formatCents(
modelValue ?? 0,
props.currency,
organization?.value?.currency_format,
organization?.value?.currency_symbol,
organization?.value?.number_format
);
return formattedValue
.replace(getOrganizationCurrencySymbol(props.currency), '')
?.replace(organization?.value?.currency_symbol ?? '', '')
.trim();
}

View File

@@ -1,10 +1,14 @@
<script setup lang="ts">
import { formatCents } from '@/packages/ui/src/utils/money';
import BillableRateModal from '@/packages/ui/src/BillableRateModal.vue';
import { inject, type ComputedRef } from 'vue';
import type { Organization } from '@/packages/api/src';
const show = defineModel('show', { default: false });
const saving = defineModel('saving', { default: false });
const organization = inject<ComputedRef<Organization>>('organization');
defineProps<{
newBillableRate?: number | null;
projectName: string;
@@ -26,7 +30,13 @@ defineEmits<{
The billable rate of {{ projectName }} will be updated to
<strong>{{
newBillableRate
? formatCents(newBillableRate, currency)
? formatCents(
newBillableRate,
currency,
organization?.currency_format,
organization?.currency_symbol,
organization?.number_format
)
: ' the default rate of the organization member'
}}</strong
>.

View File

@@ -1,12 +1,52 @@
function formatMoney(amount: number, currency: string) {
return new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: currency,
}).format(amount);
import { formatNumber, type NumberFormat } from './number';
export type CurrencyFormat =
| 'iso-code-before-with-space'
| 'iso-code-after-with-space'
| 'symbol-before'
| 'symbol-after'
| 'symbol-before-with-space'
| 'symbol-after-with-space';
function formatMoney(
amount: number,
currency?: string,
format?: CurrencyFormat,
currencySymbol?: string,
numberFormat?: NumberFormat
) {
const formattedAmount = formatNumber(amount, numberFormat);
switch (format) {
case 'iso-code-before-with-space':
return `${currency} ${formattedAmount}`;
case 'iso-code-after-with-space':
return `${formattedAmount} ${currency}`;
case 'symbol-before':
return `${currencySymbol}${formattedAmount}`;
case 'symbol-after':
return `${formattedAmount}${currencySymbol}`;
case 'symbol-before-with-space':
return `${currencySymbol} ${formattedAmount}`;
case 'symbol-after-with-space':
return `${formattedAmount} ${currencySymbol}`;
}
}
export function formatCents(amount: number, currency: string) {
return formatMoney(amount / 100, currency);
export function formatCents(
amount: number,
currency?: string,
format?: CurrencyFormat,
currencySymbol?: string,
numberFormat?: NumberFormat
) {
return formatMoney(
amount / 100,
currency,
format,
currencySymbol,
numberFormat
);
}
export function getOrganizationCurrencySymbol(currency: string) {