feat(GeneralPage): implement timezone selection with dynamic loading and error handling

This commit is contained in:
Jaime Idolpx 2026-06-08 03:39:06 -04:00
parent 135d10861d
commit f82b669fe2

View File

@ -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>
<input {!tzError && timezones ? (
type="text" <select
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" className="w-full px-3 py-2 border border-neutral-300 rounded-lg"
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
type="text"
value={general.timezone || ''}
onChange={(e) => updateSetting(['general', 'timezone'], e.target.value)}
placeholder={timezones === null && !tzError ? 'Loading…' : 'America/Los_Angeles'}
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">