Client - handle date string format depending on language
This commit is contained in:
parent
6fce510a0a
commit
d1c658b5bb
@ -130,7 +130,8 @@
|
|||||||
import { TAppConfig } from '@/types/application'
|
import { TAppConfig } from '@/types/application'
|
||||||
import { IAuthUserProfile, IUserProfile } from '@/types/user'
|
import { IAuthUserProfile, IUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
import { formatDate } from '@/utils/dates'
|
import { formatDate, getDateFormat } from '@/utils/dates'
|
||||||
|
import { localeFromLanguage } from '@/utils/locales'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: IUserProfile
|
user: IUserProfile
|
||||||
@ -143,6 +144,9 @@
|
|||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const { user, fromAdmin } = toRefs(props)
|
const { user, fromAdmin } = toRefs(props)
|
||||||
|
const language: ComputedRef<string> = computed(
|
||||||
|
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
||||||
|
)
|
||||||
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
||||||
() => store.getters[AUTH_USER_STORE.GETTERS.AUTH_USER_PROFILE]
|
() => store.getters[AUTH_USER_STORE.GETTERS.AUTH_USER_PROFILE]
|
||||||
)
|
)
|
||||||
@ -157,7 +161,11 @@
|
|||||||
)
|
)
|
||||||
const birthDate = computed(() =>
|
const birthDate = computed(() =>
|
||||||
props.user.birth_date
|
props.user.birth_date
|
||||||
? format(new Date(props.user.birth_date), authUser.value.date_format)
|
? format(
|
||||||
|
new Date(props.user.birth_date),
|
||||||
|
`${getDateFormat(authUser.value.date_format, language.value)}`,
|
||||||
|
{ locale: localeFromLanguage[language.value] }
|
||||||
|
)
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
const isSuccess = computed(
|
const isSuccess = computed(
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
<div id="user-preferences" class="description-list">
|
<div id="user-preferences" class="description-list">
|
||||||
<dl>
|
<dl>
|
||||||
<dt>{{ $t('user.PROFILE.LANGUAGE') }}:</dt>
|
<dt>{{ $t('user.PROFILE.LANGUAGE') }}:</dt>
|
||||||
<dd>{{ language }}</dd>
|
<dd>{{ userLanguage }}</dd>
|
||||||
<dt>{{ $t('user.PROFILE.TIMEZONE') }}:</dt>
|
<dt>{{ $t('user.PROFILE.TIMEZONE') }}:</dt>
|
||||||
<dd>{{ timezone }}</dd>
|
<dd>{{ timezone }}</dd>
|
||||||
<dt>{{ $t('user.PROFILE.DATE_FORMAT') }}:</dt>
|
<dt>{{ $t('user.PROFILE.DATE_FORMAT') }}:</dt>
|
||||||
<dd>{{ date_format }}</dd>
|
<dd>{{ getDateFormat(date_format, appLanguage) }}</dd>
|
||||||
<dt>{{ $t('user.PROFILE.FIRST_DAY_OF_WEEK') }}:</dt>
|
<dt>{{ $t('user.PROFILE.FIRST_DAY_OF_WEEK') }}:</dt>
|
||||||
<dd>{{ $t(`user.PROFILE.${fistDayOfWeek}`) }}</dd>
|
<dd>{{ $t(`user.PROFILE.${fistDayOfWeek}`) }}</dd>
|
||||||
<dt>{{ $t('user.PROFILE.UNITS.LABEL') }}:</dt>
|
<dt>{{ $t('user.PROFILE.UNITS.LABEL') }}:</dt>
|
||||||
@ -30,9 +30,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed, ComputedRef } from 'vue'
|
||||||
|
|
||||||
|
import { ROOT_STORE } from '@/store/constants'
|
||||||
import { IAuthUserProfile } from '@/types/user'
|
import { IAuthUserProfile } from '@/types/user'
|
||||||
|
import { useStore } from '@/use/useStore'
|
||||||
|
import { getDateFormat } from '@/utils/dates'
|
||||||
import { languageLabels } from '@/utils/locales'
|
import { languageLabels } from '@/utils/locales'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -40,7 +43,12 @@
|
|||||||
}
|
}
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const language = computed(() =>
|
const store = useStore()
|
||||||
|
|
||||||
|
const appLanguage: ComputedRef<string> = computed(
|
||||||
|
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
||||||
|
)
|
||||||
|
const userLanguage = computed(() =>
|
||||||
props.user.language
|
props.user.language
|
||||||
? languageLabels[props.user.language]
|
? languageLabels[props.user.language]
|
||||||
: languageLabels['en']
|
: languageLabels['en']
|
||||||
@ -50,7 +58,7 @@
|
|||||||
props.user.timezone ? props.user.timezone : 'Europe/Paris'
|
props.user.timezone ? props.user.timezone : 'Europe/Paris'
|
||||||
)
|
)
|
||||||
const date_format = computed(() =>
|
const date_format = computed(() =>
|
||||||
props.user.date_format ? props.user.date_format : 'dd/MM/yyyy'
|
props.user.date_format ? props.user.date_format : 'MM/dd/yyyy'
|
||||||
)
|
)
|
||||||
const display_ascent = computed(() =>
|
const display_ascent = computed(() =>
|
||||||
props.user.display_ascent ? 'DISPLAYED' : 'HIDDEN'
|
props.user.display_ascent ? 'DISPLAYED' : 'HIDDEN'
|
||||||
|
@ -26,15 +26,17 @@
|
|||||||
<label class="form-items">
|
<label class="form-items">
|
||||||
{{ $t('user.PROFILE.DATE_FORMAT') }}
|
{{ $t('user.PROFILE.DATE_FORMAT') }}
|
||||||
<select
|
<select
|
||||||
name="date_format"
|
id="date_format"
|
||||||
:disabled="loading"
|
|
||||||
v-model="userForm.date_format"
|
v-model="userForm.date_format"
|
||||||
|
:disabled="loading"
|
||||||
>
|
>
|
||||||
<option disabled value="">Please select one:</option>
|
<option
|
||||||
<option value="dd/MM/yyyy">dd/MM/yyyy - 08/07/2022</option>
|
v-for="dateFormat in dateFormatOptions"
|
||||||
<option value="MM/dd/yyyy">MM/dd/yyyy - 07/08/2022</option>
|
:value="dateFormat.value"
|
||||||
<option value="MMM. do, yyyy">MMM. do, yyyy - Jul. 8th, 2022</option>
|
:key="dateFormat.value"
|
||||||
<option value="yyyy-MM-dd">yyyy-MM-dd - 2022-07-08</option>
|
>
|
||||||
|
{{ dateFormat.label }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<div class="form-items form-checkboxes">
|
<div class="form-items form-checkboxes">
|
||||||
@ -120,6 +122,7 @@
|
|||||||
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||||
import { IUserPreferencesPayload, IAuthUserProfile } from '@/types/user'
|
import { IUserPreferencesPayload, IAuthUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
|
import { availableDateFormatOptions } from '@/utils/dates'
|
||||||
import { availableLanguages } from '@/utils/locales'
|
import { availableLanguages } from '@/utils/locales'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -173,6 +176,13 @@
|
|||||||
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||||
)
|
)
|
||||||
|
const dateFormatOptions = computed(() =>
|
||||||
|
availableDateFormatOptions(
|
||||||
|
new Date().toUTCString(),
|
||||||
|
props.user.timezone,
|
||||||
|
userForm.language
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.user) {
|
if (props.user) {
|
||||||
|
@ -11,6 +11,11 @@ import {
|
|||||||
} from 'date-fns'
|
} from 'date-fns'
|
||||||
import { utcToZonedTime } from 'date-fns-tz'
|
import { utcToZonedTime } from 'date-fns-tz'
|
||||||
|
|
||||||
|
import createI18n from '@/i18n'
|
||||||
|
import { localeFromLanguage } from '@/utils/locales'
|
||||||
|
|
||||||
|
const { locale } = createI18n.global
|
||||||
|
|
||||||
export const getStartDate = (
|
export const getStartDate = (
|
||||||
duration: string,
|
duration: string,
|
||||||
day: Date,
|
day: Date,
|
||||||
@ -70,22 +75,70 @@ export const formatWorkoutDate = (
|
|||||||
if (!dateFormat) {
|
if (!dateFormat) {
|
||||||
dateFormat = 'yyyy/MM/dd'
|
dateFormat = 'yyyy/MM/dd'
|
||||||
}
|
}
|
||||||
|
dateFormat = getDateFormat(dateFormat, locale.value)
|
||||||
if (!timeFormat) {
|
if (!timeFormat) {
|
||||||
timeFormat = 'HH:mm'
|
timeFormat = 'HH:mm'
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
workout_date: format(dateTime, dateFormat),
|
workout_date: format(dateTime, dateFormat, {
|
||||||
|
locale: localeFromLanguage[locale.value],
|
||||||
|
}),
|
||||||
workout_time: format(dateTime, timeFormat),
|
workout_time: format(dateTime, timeFormat),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const availableDateFormats = [
|
||||||
|
'dd/MM/yyyy',
|
||||||
|
'MM/dd/yyyy',
|
||||||
|
'yyyy-MM-dd',
|
||||||
|
'date_string',
|
||||||
|
]
|
||||||
|
const dateStringFormats: Record<string, string> = {
|
||||||
|
de: 'd MMM yyyy',
|
||||||
|
en: 'MMM. do, yyyy',
|
||||||
|
fr: 'd MMM yyyy',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getDateFormat = (dateFormat: string, language: string): string => {
|
||||||
|
return dateFormat === 'date_string' ? dateStringFormats[language] : dateFormat
|
||||||
|
}
|
||||||
|
|
||||||
export const formatDate = (
|
export const formatDate = (
|
||||||
dateString: string,
|
dateString: string,
|
||||||
timezone: string,
|
timezone: string,
|
||||||
dateFormat: string,
|
dateFormat: string,
|
||||||
withTime = true
|
withTime = true,
|
||||||
): string =>
|
language: string | null = null
|
||||||
format(
|
): string => {
|
||||||
|
if (!language) {
|
||||||
|
language = locale.value
|
||||||
|
}
|
||||||
|
return format(
|
||||||
getDateWithTZ(dateString, timezone),
|
getDateWithTZ(dateString, timezone),
|
||||||
`${dateFormat}${withTime ? ' HH:mm' : ''}`
|
`${getDateFormat(dateFormat, language)}${withTime ? ' HH:mm' : ''}`,
|
||||||
|
{ locale: localeFromLanguage[language] }
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const availableDateFormatOptions = (
|
||||||
|
inputDate: string,
|
||||||
|
timezone: string,
|
||||||
|
language: string | null = null
|
||||||
|
) => {
|
||||||
|
const l: string = language ? language : locale.value
|
||||||
|
const options: Record<string, string>[] = []
|
||||||
|
availableDateFormats.map((df) => {
|
||||||
|
const dateFormat = getDateFormat(df, l)
|
||||||
|
options.push({
|
||||||
|
label: `${dateFormat} - ${formatDate(
|
||||||
|
inputDate,
|
||||||
|
timezone,
|
||||||
|
dateFormat,
|
||||||
|
false,
|
||||||
|
l
|
||||||
|
)}`,
|
||||||
|
value: df,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
import createI18n from '@/i18n'
|
||||||
import { ITranslatedSport } from '@/types/sports'
|
import { ITranslatedSport } from '@/types/sports'
|
||||||
import { TUnit } from '@/types/units'
|
import { TUnit } from '@/types/units'
|
||||||
import { ICardRecord, IRecord, IRecordsBySports } from '@/types/workouts'
|
import { ICardRecord, IRecord, IRecordsBySports } from '@/types/workouts'
|
||||||
import { formatWorkoutDate, getDateWithTZ } from '@/utils/dates'
|
import { formatDate, getDateFormat } from '@/utils/dates'
|
||||||
import { convertDistance, units } from '@/utils/units'
|
import { convertDistance, units } from '@/utils/units'
|
||||||
|
|
||||||
|
const { locale } = createI18n.global
|
||||||
|
|
||||||
export const formatRecord = (
|
export const formatRecord = (
|
||||||
record: IRecord,
|
record: IRecord,
|
||||||
tz: string,
|
tz: string,
|
||||||
@ -54,8 +57,7 @@ export const formatRecord = (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
workout_date: formatWorkoutDate(getDateWithTZ(record.workout_date, tz), date_format)
|
workout_date: formatDate(record.workout_date, tz, date_format, false),
|
||||||
.workout_date,
|
|
||||||
workout_id: record.workout_id,
|
workout_id: record.workout_id,
|
||||||
id: record.id,
|
id: record.id,
|
||||||
record_type: record.record_type,
|
record_type: record.record_type,
|
||||||
@ -76,8 +78,9 @@ export const getRecordsBySports = (
|
|||||||
useImperialUnits: boolean,
|
useImperialUnits: boolean,
|
||||||
display_ascent: boolean,
|
display_ascent: boolean,
|
||||||
date_format: string
|
date_format: string
|
||||||
): IRecordsBySports =>
|
): IRecordsBySports => {
|
||||||
records
|
date_format = getDateFormat(date_format, locale.value)
|
||||||
|
return records
|
||||||
.filter((r) => (display_ascent ? true : r.record_type !== 'HA'))
|
.filter((r) => (display_ascent ? true : r.record_type !== 'HA'))
|
||||||
.reduce((sportList: IRecordsBySports, record) => {
|
.reduce((sportList: IRecordsBySports, record) => {
|
||||||
const sport = translatedSports.find((s) => s.id === record.sport_id)
|
const sport = translatedSports.find((s) => s.id === record.sport_id)
|
||||||
@ -95,3 +98,4 @@ export const getRecordsBySports = (
|
|||||||
}
|
}
|
||||||
return sportList
|
return sportList
|
||||||
}, {})
|
}, {})
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@ import {
|
|||||||
getStartDate,
|
getStartDate,
|
||||||
formatWorkoutDate,
|
formatWorkoutDate,
|
||||||
formatDate,
|
formatDate,
|
||||||
|
availableDateFormatOptions,
|
||||||
|
getDateFormat,
|
||||||
} from '@/utils/dates'
|
} from '@/utils/dates'
|
||||||
|
|
||||||
describe('startDate (week starting Sunday)', () => {
|
describe('startDate (week starting Sunday)', () => {
|
||||||
@ -290,3 +292,109 @@ describe('formatDate (w/ default value)', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('getDateFormat', () => {
|
||||||
|
const testsParams = [
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'dd/MM/yyyy',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'dd/MM/yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'MM/dd/yyyy',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'MM/dd/yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'yyyy-MM-dd',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'yyyy-MM-dd',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'date_string',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'MMM. do, yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'date_string',
|
||||||
|
language: 'fr',
|
||||||
|
},
|
||||||
|
expectedFormat: 'd MMM yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'date_string',
|
||||||
|
language: 'de',
|
||||||
|
},
|
||||||
|
expectedFormat: 'd MMM yyyy',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
testsParams.map((testParams) => {
|
||||||
|
it(`get date format for "${testParams.inputParams.language}" and "${testParams.inputParams.dateFormat}" `, () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
getDateFormat(
|
||||||
|
testParams.inputParams.dateFormat,
|
||||||
|
testParams.inputParams.language
|
||||||
|
),
|
||||||
|
testParams.expectedFormat
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('availableDateFormatOptions', () => {
|
||||||
|
const inputDate = `Sun, 9 Oct 2022 18:18:41 GMT`
|
||||||
|
const inputTimezone = `Europe/Paris`
|
||||||
|
|
||||||
|
const testsParams = [
|
||||||
|
{
|
||||||
|
inputLanguage: 'en',
|
||||||
|
expectedOptions: [
|
||||||
|
{ label: 'dd/MM/yyyy - 09/10/2022', value: 'dd/MM/yyyy' },
|
||||||
|
{ label: 'MM/dd/yyyy - 10/09/2022', value: 'MM/dd/yyyy' },
|
||||||
|
{ label: 'yyyy-MM-dd - 2022-10-09', value: 'yyyy-MM-dd' },
|
||||||
|
{ label: 'MMM. do, yyyy - Oct. 9th, 2022', value: 'date_string' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLanguage: 'fr',
|
||||||
|
expectedOptions: [
|
||||||
|
{ label: 'dd/MM/yyyy - 09/10/2022', value: 'dd/MM/yyyy' },
|
||||||
|
{ label: 'MM/dd/yyyy - 10/09/2022', value: 'MM/dd/yyyy' },
|
||||||
|
{ label: 'yyyy-MM-dd - 2022-10-09', value: 'yyyy-MM-dd' },
|
||||||
|
{ label: 'd MMM yyyy - 9 oct. 2022', value: 'date_string' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLanguage: 'de',
|
||||||
|
expectedOptions: [
|
||||||
|
{ label: 'dd/MM/yyyy - 09/10/2022', value: 'dd/MM/yyyy' },
|
||||||
|
{ label: 'MM/dd/yyyy - 10/09/2022', value: 'MM/dd/yyyy' },
|
||||||
|
{ label: 'yyyy-MM-dd - 2022-10-09', value: 'yyyy-MM-dd' },
|
||||||
|
{ label: 'd MMM yyyy - 9 Okt. 2022', value: 'date_string' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
testsParams.map((testParams) => {
|
||||||
|
it(`returns available options for ${testParams.inputLanguage} locale`, () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
availableDateFormatOptions(
|
||||||
|
inputDate,
|
||||||
|
inputTimezone,
|
||||||
|
testParams.inputLanguage
|
||||||
|
),
|
||||||
|
testParams.expectedOptions
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user