Better settings ui

This commit is contained in:
2025-10-13 14:01:13 +02:00
parent 3b98a94c19
commit 2c061a6f8e
6 changed files with 131 additions and 83 deletions
-71
View File
@@ -1,71 +0,0 @@
"use client";
import { useProfileSettings, useClientSettings } from "@/hooks/use-settings";
import { setClientSettings } from "@/lib/clientSettings";
import Settings from "./settings";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Card } from "@/components/ui/card";
import { CardContent } from "@/components/ui/card";
import { PROFILE_SCHEMA, CLIENT_SCHEMA } from "@/types/settings";
import { useParams, useRouter, useSearchParams } from "next/navigation";
import { Button } from "@/components/ui/button";
import { ChevronLeftCircle } from "lucide-react";
import axios from "axios";
import { useEffect } from "react";
export default function SettingsPage() {
const [settings, setSettings] = useClientSettings();
const [profileSettings, setProfileSettings] = useProfileSettings();
const router = useRouter();
const params = useSearchParams();
return (
<div>
<Button
variant="outline"
className="ml-2 mt-2"
onClick={() => router.back()}
>
<ChevronLeftCircle />
</Button>
<Tabs
className="mx-auto mt-3"
defaultValue={params.get("tab") || "client"}
>
<TabsList className="mx-auto">
<TabsTrigger value="client">Client Settings</TabsTrigger>
<TabsTrigger value="profile">Profile Settings</TabsTrigger>
</TabsList>
<TabsContent value="client">
<Card className="w-xl mx-auto">
<CardContent className="flex flex-col gap-3">
<Settings
settings={settings}
setSettings={setSettings}
schema={CLIENT_SCHEMA}
onSave={() => {
setClientSettings(settings);
router.refresh();
}}
/>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="profile">
<Card className="w-xl mx-auto">
<CardContent className="flex flex-col gap-3">
<Settings
settings={profileSettings}
setSettings={setProfileSettings}
schema={PROFILE_SCHEMA}
onSave={async () => {
await axios.post("/api/profile", profileSettings);
}}
/>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
);
}
+6 -9
View File
@@ -33,6 +33,7 @@ import ProfilePicture from "./ProfilePicture";
import auth, { makeAddress } from "@/lib/auth";
import { toast } from "sonner";
import { StringMap } from "@/types/typeUtils";
import SettingsDialog from "./settings/SettingsDialog";
export default function AppSidebar({
children,
@@ -195,9 +196,7 @@ export default function AppSidebar({
</Dialog>
<footer className="mt-auto">
<Link href="/settings">
<SettingsIcon />
</Link>
<SettingsDialog />
</footer>
</div>
@@ -271,12 +270,10 @@ function DMItem({
<span className="text-xs text-muted-foreground">{status}</span>
</div>
{settings && (
<Button
onClick={() => router.push(`/settings?tab=profile`)}
className="bg-transparent text-accent-foreground hover:text-accent ml-auto w-7 h-7 p-0 flex items-center justify-center rounded-md"
>
<SettingsIcon size={16} />
</Button>
<SettingsDialog
className="ml-auto w-7 h-7 p-0 flex items-center justify-center"
tab="profile"
/>
)}
</Card>
);
@@ -25,7 +25,7 @@ export type SettingsSchema = StringMap<
"boolean" | "string" | "number" | string[] | RegexSetting
>;
export default function Settings<T>({
export default function SettingSchema<T>({
settings,
setSettings,
schema,
@@ -73,7 +73,7 @@ export default function Settings<T>({
value={(settings as any)[key] || []}
onValueChange={(val) => handleChange(key, val)}
>
<SelectTrigger className="w-[200px]">
<SelectTrigger>
<SelectValue placeholder={key} />
</SelectTrigger>
<SelectContent>
+66
View File
@@ -0,0 +1,66 @@
"use client";
import { useClientSettings } from "@/hooks/use-settings";
import { setClientSettings } from "@/lib/clientSettings";
import SettingSchema from "./SettingSchema";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Card } from "@/components/ui/card";
import { CardContent } from "@/components/ui/card";
import {
PROFILE_SCHEMA,
CLIENT_SCHEMA,
ProfileSettings,
} from "@/types/settings";
import { useParams, useRouter, useSearchParams } from "next/navigation";
import axios from "axios";
export default function Settings({
tab,
profileSettings,
setProfileSettings,
}: {
tab?: string;
profileSettings: ProfileSettings;
setProfileSettings: React.Dispatch<React.SetStateAction<ProfileSettings>>;
}) {
const [settings, setSettings] = useClientSettings();
const router = useRouter();
return (
<Tabs className="mx-auto mt-3" defaultValue={tab || "client"}>
<TabsList className="mx-auto">
<TabsTrigger value="client">Client Settings</TabsTrigger>
<TabsTrigger value="profile">Profile Settings</TabsTrigger>
</TabsList>
<TabsContent value="client">
<Card className="mx-auto">
<CardContent className="flex flex-col gap-3">
<SettingSchema
settings={settings}
setSettings={setSettings}
schema={CLIENT_SCHEMA}
onSave={() => {
setClientSettings(settings);
router.refresh();
}}
/>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="profile">
<Card className="mx-auto">
<CardContent className="flex flex-col gap-3">
<SettingSchema
settings={profileSettings}
setSettings={setProfileSettings}
schema={PROFILE_SCHEMA}
onSave={async () => {
await axios.post("/api/profile", profileSettings);
}}
/>
</CardContent>
</Card>
</TabsContent>
</Tabs>
);
}
@@ -0,0 +1,53 @@
import { SettingsIcon } from "lucide-react";
import { Button } from "../ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
import { cn } from "@/lib/utils";
import Settings from "./Settings";
import { ProfileSettings } from "@/types/settings";
import { useProfileSettings } from "@/hooks/use-settings";
export default function SettingsDialog({
className,
tab,
}: {
className?: string;
tab?: string;
profile?: ProfileSettings;
}) {
const [profileSettings, setProfileSettings] = useProfileSettings();
return (
<Dialog>
<DialogTrigger asChild>
<Button
className={cn(
"bg-transparent text-accent-foreground hover:text-accent",
className
)}
>
<SettingsIcon />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Settings</DialogTitle>
</DialogHeader>
<div className="w-full">
<Settings
tab={tab}
profileSettings={profileSettings}
setProfileSettings={setProfileSettings}
/>
</div>
</DialogContent>
</Dialog>
);
}
+4 -1
View File
@@ -1,4 +1,7 @@
import { RegexSetting, SettingsSchema } from "@/app/settings/settings";
import {
RegexSetting,
SettingsSchema,
} from "@/components/settings/SettingSchema";
export interface ClientSettings {
theme: "light" | "dark";