[] = [updateSettings({ ...form })]
+ if (timezone.value !== (bot.value?.timezone || '')) {
+ promises.push(updateBot({ id: botIdRef.value, timezone: timezone.value }))
+ }
+ await Promise.all(promises)
toast.success(t('bots.settings.saveSuccess'))
} catch {
return
diff --git a/apps/web/src/pages/bots/detail.vue b/apps/web/src/pages/bots/detail.vue
index 2bc577b0..d4fd0af3 100644
--- a/apps/web/src/pages/bots/detail.vue
+++ b/apps/web/src/pages/bots/detail.vue
@@ -93,22 +93,6 @@
{{ botTypeLabel }}
-
- {{ $t('bots.timezone') }}: {{ bot.timezone || $t('bots.timezoneInherited') }}
-
-
@@ -209,67 +193,6 @@
-
-
@@ -288,12 +211,6 @@ import {
DialogHeader,
DialogTitle,
Input,
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectTrigger,
- SelectValue,
Separator,
Spinner,
ScrollArea,
@@ -338,7 +255,6 @@ import { useAvatarInitials } from '@/composables/useAvatarInitials'
import { useSyncedQueryParam } from '@/composables/useSyncedQueryParam'
import { useBotStatusMeta } from '@/composables/useBotStatusMeta'
import MasterDetailSidebarLayout from '@/components/master-detail-sidebar-layout/index.vue'
-import { emptyTimezoneValue, timezones } from '@/utils/timezones'
type BotCheck = BotsBotCheck
type BotContainerInfo = HandlersGetContainerResponse
type BotContainerSnapshot = HandlersListSnapshotsResponse extends { snapshots?: (infer T)[] } ? T : never
@@ -428,12 +344,9 @@ watch(bot, (val) => {
const activeTab = useSyncedQueryParam('tab', 'overview')
const avatarDialogOpen = ref(false)
const avatarUrlDraft = ref('')
-const timezoneDialogOpen = ref(false)
-const timezoneDraft = ref('')
const avatarFallback = useAvatarInitials(() => bot.value?.display_name || botId.value || '')
const isSavingBotName = computed(() => updateBotLoading.value)
const avatarSaving = computed(() => updateBotLoading.value)
-const timezoneSaving = computed(() => updateBotLoading.value)
const canConfirmAvatar = computed(() => {
if (!bot.value) return false
const next = avatarUrlDraft.value.trim()
@@ -446,10 +359,6 @@ const canConfirmBotName = computed(() => {
if (!nextName) return false
return nextName !== (bot.value.display_name || '').trim()
})
-const canConfirmTimezone = computed(() => {
- if (!bot.value) return false
- return timezoneDraft.value.trim() !== (bot.value.timezone || '').trim()
-})
const {
hasIssue,
isPending: botLifecyclePending,
@@ -503,12 +412,6 @@ function handleEditAvatar() {
avatarDialogOpen.value = true
}
-function handleEditTimezone() {
- if (!bot.value || botLifecyclePending.value) return
- timezoneDraft.value = bot.value.timezone || ''
- timezoneDialogOpen.value = true
-}
-
async function handleConfirmAvatar() {
if (!bot.value || !canConfirmAvatar.value || avatarSaving.value) return
const nextUrl = avatarUrlDraft.value.trim()
@@ -524,21 +427,6 @@ async function handleConfirmAvatar() {
}
}
-async function handleConfirmTimezone() {
- if (!bot.value || !canConfirmTimezone.value || timezoneSaving.value) return
- const nextTimezone = timezoneDraft.value.trim()
- try {
- await updateBot({
- id: bot.value.id as string,
- timezone: nextTimezone,
- })
- timezoneDialogOpen.value = false
- toast.success(t('bots.timezoneUpdateSuccess'))
- } catch (error) {
- toast.error(resolveErrorMessage(error, t('bots.timezoneUpdateFailed')))
- }
-}
-
function handleStartEditBotName() {
if (!bot.value) return
isEditingBotName.value = true
diff --git a/apps/web/src/pages/browser-contexts/components/context-setting.vue b/apps/web/src/pages/browser-contexts/components/context-setting.vue
index 13dd68fe..8a2fb5b9 100644
--- a/apps/web/src/pages/browser-contexts/components/context-setting.vue
+++ b/apps/web/src/pages/browser-contexts/components/context-setting.vue
@@ -149,34 +149,19 @@
-
+ handleChange(val === emptyTimezoneValue ? '' : val)"
+ />
@@ -249,12 +234,6 @@ import {
Label,
Separator,
Button,
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectTrigger,
- SelectValue,
Switch,
} from '@memohai/ui'
import { toTypedSchema } from '@vee-validate/zod'
@@ -270,7 +249,8 @@ import { toast } from 'vue-sonner'
import { useDialogMutation } from '@/composables/useDialogMutation'
import ConfirmPopover from '@/components/confirm-popover/index.vue'
import { resolveApiErrorMessage } from '@/utils/api-error'
-import { emptyTimezoneValue, timezones } from '@/utils/timezones'
+import { emptyTimezoneValue } from '@/utils/timezones'
+import TimezoneSelect from '@/components/timezone-select/index.vue'
const { t } = useI18n()
const { run } = useDialogMutation()
diff --git a/apps/web/src/pages/settings/components/profile-section.vue b/apps/web/src/pages/settings/components/profile-section.vue
index 0d8d0abf..ed7b41ee 100644
--- a/apps/web/src/pages/settings/components/profile-section.vue
+++ b/apps/web/src/pages/settings/components/profile-section.vue
@@ -48,29 +48,11 @@
-
+ />