feat(GeneralPage): implement timezone selection with dynamic loading and error handling
This commit is contained in:
parent
135d10861d
commit
f82b669fe2
|
|
@ -1,9 +1,30 @@
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { getFileContents } from '../webdav';
|
||||||
|
|
||||||
interface GeneralPageProps {
|
interface GeneralPageProps {
|
||||||
config: any;
|
config: any;
|
||||||
setConfig: (config: any) => void;
|
setConfig: (config: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function GeneralPage({ config, setConfig }: GeneralPageProps) {
|
export default function GeneralPage({ config, setConfig }: GeneralPageProps) {
|
||||||
|
const [timezones, setTimezones] = useState<string[] | null>(null);
|
||||||
|
const [tzError, setTzError] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getFileContents('/.sys/timezones.json')
|
||||||
|
.then(async (blob) => {
|
||||||
|
const parsed = JSON.parse(await blob.text());
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
setTimezones(parsed.map((e: any) => (typeof e === 'string' ? e : String(e.name ?? e.value ?? e))));
|
||||||
|
} else if (parsed && typeof parsed === 'object') {
|
||||||
|
setTimezones(Object.keys(parsed));
|
||||||
|
} else {
|
||||||
|
setTzError(true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => setTzError(true));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const updateSetting = (path: string[], value: any) => {
|
const updateSetting = (path: string[], value: any) => {
|
||||||
const newConfig = JSON.parse(JSON.stringify(config));
|
const newConfig = JSON.parse(JSON.stringify(config));
|
||||||
let current = newConfig;
|
let current = newConfig;
|
||||||
|
|
@ -51,13 +72,29 @@ export default function GeneralPage({ config, setConfig }: GeneralPageProps) {
|
||||||
|
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<label className="text-sm text-neutral-500 block mb-2">Timezone</label>
|
<label className="text-sm text-neutral-500 block mb-2">Timezone</label>
|
||||||
|
{!tzError && timezones ? (
|
||||||
|
<select
|
||||||
|
value={general.timezone || ''}
|
||||||
|
onChange={(e) => updateSetting(['general', 'timezone'], e.target.value)}
|
||||||
|
className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
|
||||||
|
>
|
||||||
|
{general.timezone && !timezones.includes(general.timezone) && (
|
||||||
|
<option value={general.timezone}>{general.timezone}</option>
|
||||||
|
)}
|
||||||
|
{timezones.map((tz) => (
|
||||||
|
<option key={tz} value={tz}>{tz}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
) : (
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={general.timezone || ''}
|
value={general.timezone || ''}
|
||||||
onChange={(e) => updateSetting(['general', 'timezone'], e.target.value)}
|
onChange={(e) => updateSetting(['general', 'timezone'], e.target.value)}
|
||||||
placeholder="America/Los_Angeles"
|
placeholder={timezones === null && !tzError ? 'Loading…' : 'America/Los_Angeles'}
|
||||||
className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
|
disabled={timezones === null && !tzError}
|
||||||
|
className="w-full px-3 py-2 border border-neutral-300 rounded-lg disabled:opacity-50"
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user