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;
+}