From 216b2d7180b8e77500e01acd749197887c7b14de Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 24 Mar 2025 18:14:27 +0100 Subject: [PATCH] fix(settings): move time zone selection to dropdown --- frontend/src/views/user/settings/General.vue | 108 ++++++++++++++----- 1 file changed, 79 insertions(+), 29 deletions(-) diff --git a/frontend/src/views/user/settings/General.vue b/frontend/src/views/user/settings/General.vue index 35690d065..9e5a2972d 100644 --- a/frontend/src/views/user/settings/General.vue +++ b/frontend/src/views/user/settings/General.vue @@ -224,16 +224,15 @@ {{ $t('user.settings.general.timezone') }} -
- -
+ @@ -259,6 +258,7 @@ import {useI18n} from 'vue-i18n' import {PrefixMode} from '@/modules/parseTaskText' import ProjectSearch from '@/components/tasks/partials/ProjectSearch.vue' +import Multiselect from '@/components/input/Multiselect.vue' import {SUPPORTED_LOCALES} from '@/i18n' import {createRandomID} from '@/helpers/randomId' @@ -284,25 +284,6 @@ const colorSchemeSettings = computed(() => ({ dark: t('user.settings.appearance.colorScheme.dark'), })) -function useAvailableTimezones() { - const availableTimezones = ref([]) - - const HTTP = AuthenticatedHTTPFactory() - HTTP.get('user/timezones') - .then(r => { - if (r.data) { - availableTimezones.value = r.data.sort() - return - } - - availableTimezones.value = [] - }) - - return availableTimezones -} - -const availableTimezones = useAvailableTimezones() - const authStore = useAuthStore() const settings = ref({ @@ -317,6 +298,70 @@ const settings = ref({ minimumPriority: authStore.settings.frontendSettings.minimumPriority ?? PRIORITIES.HIGH, }, }) + +function useAvailableTimezones(settingsRef: Ref) { + const availableTimezones = ref<{value: string, label: string}[]>([]) + const searchResults = ref<{value: string, label: string}[]>([]) + + // Load timezones from API + const HTTP = AuthenticatedHTTPFactory() + HTTP.get('user/timezones') + .then(r => { + if (r.data) { + // Transform timezones into objects with value/label pairs + availableTimezones.value = r.data + .sort() + .map((tz: string) => ({ + value: tz, + label: tz.replace(/_/g, ' '), + })) + + // Initial populate of search results + searchResults.value = [...availableTimezones.value] + return + } + + availableTimezones.value = [] + }) + + // Search function that filters available timezones + function search(query: string) { + if (query === '') { + searchResults.value = [...availableTimezones.value] + return + } + + searchResults.value = availableTimezones.value + .filter(tz => tz.label.toLowerCase().includes(query.toLowerCase())) + } + + const timezoneObject = computed({ + get: () => ({ + value: settingsRef.value.timezone, + label: settingsRef.value.timezone?.replace(/_/g, ' '), + }), + set: (obj) => { + if (obj && typeof obj === 'object' && 'value' in obj) { + settingsRef.value.timezone = obj.value + } + }, + }) + + return { + availableTimezones, + searchResults, + search, + timezoneObject, + } +} + +// Use the timezone composable and destructure its return values +const { + searchResults: timezoneSearchResults, + search: searchTimezones, + timezoneObject, +} = useAvailableTimezones(settings) + const id = ref(createRandomID()) const availableLanguageOptions = ref( Object.entries(SUPPORTED_LOCALES) @@ -365,4 +410,9 @@ async function updateSettings() { .select select { width: 100%; } + +.timezone-select { + min-width: 200px; + flex-grow: 1; +}