Add searchable timezone settings override for reminder scheduling
This commit is contained in:
@@ -7,6 +7,9 @@ import { useTranslation } from "react-i18next";
|
||||
import { log } from "../utils/logger";
|
||||
|
||||
export interface Settings {
|
||||
timezone: string;
|
||||
availableTimezones: string[];
|
||||
serverTimezone: string;
|
||||
emailEnabled: boolean;
|
||||
notificationEmail: string;
|
||||
reminderDaysBefore: number;
|
||||
@@ -58,6 +61,9 @@ export interface Settings {
|
||||
export type SettingsLoadError = "auth" | "forbidden" | "request" | null;
|
||||
|
||||
const defaultSettings: Settings = {
|
||||
timezone: "",
|
||||
availableTimezones: [],
|
||||
serverTimezone: "UTC",
|
||||
emailEnabled: false,
|
||||
notificationEmail: "",
|
||||
reminderDaysBefore: 7,
|
||||
@@ -243,6 +249,7 @@ export function useSettings(): UseSettingsReturn {
|
||||
const repeatDailyReminders = hasAnyStockReminder ? settingsToSave.repeatDailyReminders : false;
|
||||
|
||||
return {
|
||||
timezone: settingsToSave.timezone,
|
||||
emailEnabled: effectiveEmailEnabled,
|
||||
notificationEmail: settingsToSave.notificationEmail,
|
||||
reminderDaysBefore: settingsToSave.reminderDaysBefore,
|
||||
|
||||
@@ -389,6 +389,12 @@
|
||||
"title": "Sprache",
|
||||
"select": "Sprache auswählen"
|
||||
},
|
||||
"timezone": {
|
||||
"select": "Zeitzone",
|
||||
"hint": "IANA-Zeitzone wählen. Wenn gesetzt, überschreibt sie die Server-TZ für deine Reminder-Zeitpunkte.",
|
||||
"useServerDefault": "Server-Standard nutzen",
|
||||
"currentServerTz": "Server-Standardzeitzone: {{timezone}}"
|
||||
},
|
||||
"apiKey": {
|
||||
"title": "API-Zugriff",
|
||||
"generateTitle": "API-Key erzeugen",
|
||||
|
||||
@@ -389,6 +389,12 @@
|
||||
"title": "Language",
|
||||
"select": "Select language"
|
||||
},
|
||||
"timezone": {
|
||||
"select": "Timezone",
|
||||
"hint": "Select an IANA timezone. When set, this overrides server TZ for your reminder timing.",
|
||||
"useServerDefault": "Use server default",
|
||||
"currentServerTz": "Server default timezone: {{timezone}}"
|
||||
},
|
||||
"apiKey": {
|
||||
"title": "API Access",
|
||||
"generateTitle": "Generate API key",
|
||||
|
||||
@@ -116,6 +116,23 @@ export function SettingsPage() {
|
||||
|
||||
const automaticStockCalculationId = "settings-stock-calculation-automatic";
|
||||
const manualStockCalculationId = "settings-stock-calculation-manual";
|
||||
const timezoneSuggestions =
|
||||
settings.availableTimezones.length > 0
|
||||
? settings.availableTimezones
|
||||
: (() => {
|
||||
try {
|
||||
type IntlWithSupportedValuesOf = typeof Intl & {
|
||||
supportedValuesOf?: (key: string) => string[];
|
||||
};
|
||||
const intlWithSupportedValues = Intl as IntlWithSupportedValuesOf;
|
||||
if (typeof intlWithSupportedValues.supportedValuesOf === "function") {
|
||||
return intlWithSupportedValues.supportedValuesOf("timeZone");
|
||||
}
|
||||
} catch {
|
||||
// fall through
|
||||
}
|
||||
return [settings.serverTimezone || "UTC", "UTC"];
|
||||
})();
|
||||
|
||||
return (
|
||||
<section className="grid">
|
||||
@@ -160,6 +177,35 @@ export function SettingsPage() {
|
||||
<option value="de">🇩🇪 Deutsch</option>
|
||||
</select>
|
||||
</label>
|
||||
<div className="setting-row compact" style={{ marginTop: "12px" }}>
|
||||
<div className="setting-label">
|
||||
<span>{t("settings.timezone.select")}</span>
|
||||
<span className="info-tooltip small" data-tooltip={t("settings.timezone.hint")}>
|
||||
ⓘ
|
||||
</span>
|
||||
</div>
|
||||
<div className="setting-actions" style={{ margin: 0, flexWrap: "nowrap", gap: "8px" }}>
|
||||
<input
|
||||
type="text"
|
||||
className="select-field language-select"
|
||||
value={settings.timezone}
|
||||
onChange={(e) => setSettings({ ...settings, timezone: e.target.value })}
|
||||
list="settings-timezone-suggestions"
|
||||
placeholder={settings.serverTimezone || "UTC"}
|
||||
/>
|
||||
<datalist id="settings-timezone-suggestions">
|
||||
{timezoneSuggestions.map((zone) => (
|
||||
<option key={zone} value={zone} />
|
||||
))}
|
||||
</datalist>
|
||||
<button type="button" className="ghost" onClick={() => setSettings({ ...settings, timezone: "" })}>
|
||||
{t("settings.timezone.useServerDefault")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="hint-text" style={{ marginTop: "8px" }}>
|
||||
{t("settings.timezone.currentServerTz", { timezone: settings.serverTimezone || "UTC" })}
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="card" data-testid="settings-notification-card">
|
||||
|
||||
Reference in New Issue
Block a user