feat(settings): add timezone field to General tab

- New Timezone section with text input + Detect button
- Detect auto-fills from browser Intl API
- Save calls PUT /api/settings (which now propagates to scheduler)
- Briefing tab firing timezone hint reads stored value instead of live browser API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-05 21:39:08 -04:00
parent 8ec91ceea7
commit 1357046160
+49 -1
View File
@@ -15,6 +15,27 @@ const toastStore = useToastStore();
const pushStore = usePushStore();
const assistantName = ref("");
const defaultModel = ref("");
const userTimezone = ref("");
const savingTimezone = ref(false);
const timezoneSaved = ref(false);
function detectTimezone() {
userTimezone.value = Intl.DateTimeFormat().resolvedOptions().timeZone;
}
async function saveTimezone() {
savingTimezone.value = true;
timezoneSaved.value = false;
try {
await apiPut('/api/settings', { user_timezone: userTimezone.value });
timezoneSaved.value = true;
setTimeout(() => (timezoneSaved.value = false), 2000);
} catch {
toastStore.show('Failed to save timezone', 'error');
} finally {
savingTimezone.value = false;
}
}
const backgroundModel = ref("");
const installedModels = ref<string[]>([]);
const defaultChatModel = ref("");
@@ -710,6 +731,7 @@ onMounted(async () => {
const allSettings = await apiGet<Record<string, string>>("/api/settings");
defaultModel.value = allSettings.default_model ?? "";
backgroundModel.value = allSettings.background_model ?? "";
userTimezone.value = allSettings.user_timezone ?? "";
chatRetentionDays.value = allSettings.chat_retention_days !== undefined
? Number(allSettings.chat_retention_days)
: 90;
@@ -1463,6 +1485,32 @@ function formatUserDate(iso: string): string {
</div>
</section>
<!-- Timezone -->
<section class="settings-section full-width">
<h2>Timezone</h2>
<p class="section-desc">Used to schedule briefings and format times in chat. Set this to your local IANA timezone (e.g. America/New_York, Europe/London).</p>
<div class="field">
<label for="user-timezone">Your timezone</label>
<div style="display:flex; gap:0.5rem; align-items:center">
<input
id="user-timezone"
v-model="userTimezone"
type="text"
class="input"
placeholder="e.g. America/New_York"
/>
<button class="btn-secondary" type="button" @click="detectTimezone">Detect</button>
</div>
<p class="field-hint">Click Detect to auto-fill from your browser.</p>
</div>
<div class="actions">
<button class="btn-save" @click="saveTimezone" :disabled="savingTimezone">
{{ savingTimezone ? 'Saving' : 'Save' }}
</button>
<span v-if="timezoneSaved" class="saved-msg">Saved!</span>
</div>
</section>
<!-- Model Management -->
<section class="settings-section full-width">
<div class="model-mgmt-header">
@@ -2104,7 +2152,7 @@ function formatUserDate(iso: string): string {
</div>
</div>
<p class="field-hint" style="margin-top: 0.5rem">
Firing in timezone: <strong>{{ Intl.DateTimeFormat().resolvedOptions().timeZone }}</strong>
Firing in timezone: <strong>{{ userTimezone || 'UTC (not configured — set in General settings)' }}</strong>
</p>
</section>