ba947cea87
more colour themes. I fixed the settings buttons.
129 lines
4.2 KiB
TypeScript
129 lines
4.2 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
import { Label } from "@/components/ui/label"
|
|
import { Button } from "@/components/ui/button"
|
|
import { toast } from "sonner"
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select"
|
|
|
|
interface Preferences {
|
|
timezone: string
|
|
dateFormat: string
|
|
itemsPerPage: number
|
|
}
|
|
|
|
export function UserPreferencesForm() {
|
|
const [prefs, setPrefs] = useState<Preferences>({
|
|
timezone: "america-los_angeles",
|
|
dateFormat: "mdy",
|
|
itemsPerPage: 20,
|
|
})
|
|
const [loading, setLoading] = useState(true)
|
|
const [saving, setSaving] = useState(false)
|
|
|
|
useEffect(() => {
|
|
async function load() {
|
|
try {
|
|
const res = await fetch("/api/settings/preferences")
|
|
if (res.ok) {
|
|
const json = await res.json()
|
|
setPrefs(json)
|
|
}
|
|
} catch {
|
|
// ignore
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
load()
|
|
}, [])
|
|
|
|
async function handleSave() {
|
|
setSaving(true)
|
|
try {
|
|
const res = await fetch("/api/settings/preferences", {
|
|
method: "PATCH",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(prefs),
|
|
})
|
|
if (res.ok) {
|
|
toast.success("Preferences saved")
|
|
} else {
|
|
toast.error("Failed to save preferences")
|
|
}
|
|
} catch {
|
|
toast.error("Failed to save preferences")
|
|
} finally {
|
|
setSaving(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>User Preferences</CardTitle>
|
|
<CardDescription>
|
|
Customize your experience and default settings.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="timezone">Timezone</Label>
|
|
<Select disabled={loading} value={prefs.timezone} onValueChange={(v) => setPrefs((p) => ({ ...p, timezone: v }))}>
|
|
<SelectTrigger id="timezone">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="america-new_york">Eastern Time (ET)</SelectItem>
|
|
<SelectItem value="america-chicago">Central Time (CT)</SelectItem>
|
|
<SelectItem value="america-denver">Mountain Time (MT)</SelectItem>
|
|
<SelectItem value="america-los_angeles">Pacific Time (PT)</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="date-format">Date Format</Label>
|
|
<Select disabled={loading} value={prefs.dateFormat} onValueChange={(v) => setPrefs((p) => ({ ...p, dateFormat: v }))}>
|
|
<SelectTrigger id="date-format">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="mdy">MM/DD/YYYY</SelectItem>
|
|
<SelectItem value="dmy">DD/MM/YYYY</SelectItem>
|
|
<SelectItem value="ymd">YYYY-MM-DD</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="items-per-page">Items Per Page</Label>
|
|
<Select disabled={loading} value={String(prefs.itemsPerPage)} onValueChange={(v) => setPrefs((p) => ({ ...p, itemsPerPage: parseInt(v) }))}>
|
|
<SelectTrigger id="items-per-page">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="10">10</SelectItem>
|
|
<SelectItem value="20">20</SelectItem>
|
|
<SelectItem value="50">50</SelectItem>
|
|
<SelectItem value="100">100</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
<div className="flex justify-end pt-4">
|
|
<Button onClick={handleSave} disabled={loading || saving}>
|
|
{saving ? "Saving..." : "Save Preferences"}
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|