diff --git a/frontend/components/Form/DatePicker.vue b/frontend/components/Form/DatePicker.vue index 725a6074..7422b603 100644 --- a/frontend/components/Form/DatePicker.vue +++ b/frontend/components/Form/DatePicker.vue @@ -3,13 +3,27 @@ - +
- +
@@ -38,6 +52,8 @@ const isDark = useIsDark(); + const formatDate = (date: Date | string | number) => fmtDate(date, "human", "date"); + const selected = computed({ get() { // String diff --git a/frontend/composables/use-formatters.ts b/frontend/composables/use-formatters.ts index 618ac85b..91cf9bf1 100644 --- a/frontend/composables/use-formatters.ts +++ b/frontend/composables/use-formatters.ts @@ -1,4 +1,3 @@ -import { useI18n } from "vue-i18n"; import { format, formatDistance } from "date-fns"; /* eslint import/namespace: ['error', { allowComputed: true }] */ import * as Locales from "date-fns/locale"; @@ -22,37 +21,43 @@ export async function useFormatCurrency() { } } - return (value: number | string) => fmtCurrency(value, cache.currency); + return (value: number | string) => fmtCurrency(value, cache.currency, getLocaleCode()); } export type DateTimeFormat = "relative" | "long" | "short" | "human"; export type DateTimeType = "date" | "time" | "datetime"; -function getLocale() { - const t = useI18n(); - const localeCode = (t?.locale?.value as string) ?? "en-US"; +export function getLocaleCode() { + const { $i18nGlobal } = useNuxtApp(); + return ($i18nGlobal?.locale?.value as string) ?? "en-US"; +} + +function getLocaleForDate() { + const localeCode = getLocaleCode(); const lang = localeCode.length > 1 ? localeCode.substring(0, 2) : localeCode; const region = localeCode.length > 2 ? localeCode.substring(3) : ""; return Locales[(lang + region) as keyof typeof Locales] ?? Locales[lang as keyof typeof Locales] ?? Locales.enUS; } -export function useLocaleTimeAgo(date: Date) { - return formatDistance(date, new Date(), { locale: getLocale() }); -} - -export function fmtDate(value: string | Date, fmt: DateTimeFormat = "human", type: DateTimeType = "date"): string { - const dt = typeof value === "string" ? new Date(value) : value; +export function fmtDate( + value: string | Date | number, + fmt: DateTimeFormat = "human", + type: DateTimeType = "date" +): string { + const dt = typeof value === "string" || typeof value === "number" ? new Date(value) : value; if (!dt || !validDate(dt)) { return ""; } + const localeOptions = { locale: getLocaleForDate() }; + if (fmt === "relative") { - return useLocaleTimeAgo(dt); + return `${formatDistance(dt, new Date(), { ...localeOptions, addSuffix: true })} (${fmtDate(dt, "short", "date")})`; } if (type === "time") { - return format(dt, "p", { locale: getLocale() }); + return format(dt, "p", localeOptions); } let formatStr = ""; @@ -74,5 +79,5 @@ export function fmtDate(value: string | Date, fmt: DateTimeFormat = "human", typ formatStr += "p"; } - return format(dt, formatStr, { locale: getLocale() }); + return format(dt, formatStr, localeOptions); } diff --git a/frontend/lib/datelib/datelib.ts b/frontend/lib/datelib/datelib.ts index c70dbf9e..b87922c1 100644 --- a/frontend/lib/datelib/datelib.ts +++ b/frontend/lib/datelib/datelib.ts @@ -11,7 +11,9 @@ export function format(date: Date | string): string { } export function zeroTime(date: Date): Date { - return new Date(date.getFullYear(), date.getMonth(), date.getDate()); + return new Date( + new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - date.getTimezoneOffset() * 60000 + ); } export function factorRange(offset: number = 7): [Date, Date] { diff --git a/frontend/pages/item/[id]/index/edit.vue b/frontend/pages/item/[id]/index/edit.vue index a4c0b602..b86c9dc3 100644 --- a/frontend/pages/item/[id]/index/edit.vue +++ b/frontend/pages/item/[id]/index/edit.vue @@ -99,16 +99,12 @@ let purchasePrice = 0; let soldPrice = 0; - let purchaseTime = null; if (item.value.purchasePrice) { purchasePrice = item.value.purchasePrice; } if (item.value.soldPrice) { soldPrice = item.value.soldPrice; } - if (item.value.purchaseTime && typeof item.value.purchaseTime !== "string") { - purchaseTime = new Date(item.value.purchaseTime.getTime() - item.value.purchaseTime.getTimezoneOffset() * 60000); - } console.log((item.value.purchasePrice ??= 0)); console.log((item.value.soldPrice ??= 0)); @@ -121,7 +117,7 @@ assetId: item.value.assetId, purchasePrice, soldPrice, - purchaseTime: purchaseTime as Date, + purchaseTime: item.value.purchaseTime as Date, }; const { error } = await api.items.update(itemId.value, payload); diff --git a/frontend/pages/profile.vue b/frontend/pages/profile.vue index d13301b3..37eb503d 100644 --- a/frontend/pages/profile.vue +++ b/frontend/pages/profile.vue @@ -8,6 +8,7 @@ import MdiFill from "~icons/mdi/fill"; import MdiPencil from "~icons/mdi/pencil"; import MdiAccountMultiple from "~icons/mdi/account-multiple"; + import { getLocaleCode } from "~/composables/use-formatters"; definePageMeta({ middleware: ["auth"], @@ -52,12 +53,11 @@ }); const currencyExample = computed(() => { - const formatter = new Intl.NumberFormat("en-US", { - style: "currency", - currency: currency.value ? currency.value.code : "USD", - }); + return fmtCurrency(1000, currency.value?.code ?? "USD", getLocaleCode()); + }); - return formatter.format(1000); + const dateExample = computed(() => { + return fmtDate(new Date(Date.now() - 15 * 60000), "relative"); }); const { data: group } = useAsyncData(async () => { @@ -389,6 +389,7 @@ {{ $t(`languages.${lang}`) }} ({{ $t(`languages.${lang}`, 1, { locale: lang }) }}) +

{{ $t("profile.example") }}: {{ $t("global.created") }} {{ dateExample }}

diff --git a/frontend/plugins/i18n.ts b/frontend/plugins/i18n.ts index f6994dcb..f563fd13 100644 --- a/frontend/plugins/i18n.ts +++ b/frontend/plugins/i18n.ts @@ -30,6 +30,12 @@ export default defineNuxtPlugin(({ vueApp }) => { messages: messages(), }); vueApp.use(i18n); + + return { + provide: { + i18nGlobal: i18n.global, + }, + }; }); export const messages = () => {