Better settings ui
This commit is contained in:
@@ -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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -33,6 +33,7 @@ import ProfilePicture from "./ProfilePicture";
|
|||||||
import auth, { makeAddress } from "@/lib/auth";
|
import auth, { makeAddress } from "@/lib/auth";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { StringMap } from "@/types/typeUtils";
|
import { StringMap } from "@/types/typeUtils";
|
||||||
|
import SettingsDialog from "./settings/SettingsDialog";
|
||||||
|
|
||||||
export default function AppSidebar({
|
export default function AppSidebar({
|
||||||
children,
|
children,
|
||||||
@@ -195,9 +196,7 @@ export default function AppSidebar({
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<footer className="mt-auto">
|
<footer className="mt-auto">
|
||||||
<Link href="/settings">
|
<SettingsDialog />
|
||||||
<SettingsIcon />
|
|
||||||
</Link>
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -271,12 +270,10 @@ function DMItem({
|
|||||||
<span className="text-xs text-muted-foreground">{status}</span>
|
<span className="text-xs text-muted-foreground">{status}</span>
|
||||||
</div>
|
</div>
|
||||||
{settings && (
|
{settings && (
|
||||||
<Button
|
<SettingsDialog
|
||||||
onClick={() => router.push(`/settings?tab=profile`)}
|
className="ml-auto w-7 h-7 p-0 flex items-center justify-center"
|
||||||
className="bg-transparent text-accent-foreground hover:text-accent ml-auto w-7 h-7 p-0 flex items-center justify-center rounded-md"
|
tab="profile"
|
||||||
>
|
/>
|
||||||
<SettingsIcon size={16} />
|
|
||||||
</Button>
|
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export type SettingsSchema = StringMap<
|
|||||||
"boolean" | "string" | "number" | string[] | RegexSetting
|
"boolean" | "string" | "number" | string[] | RegexSetting
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export default function Settings<T>({
|
export default function SettingSchema<T>({
|
||||||
settings,
|
settings,
|
||||||
setSettings,
|
setSettings,
|
||||||
schema,
|
schema,
|
||||||
@@ -73,7 +73,7 @@ export default function Settings<T>({
|
|||||||
value={(settings as any)[key] || []}
|
value={(settings as any)[key] || []}
|
||||||
onValueChange={(val) => handleChange(key, val)}
|
onValueChange={(val) => handleChange(key, val)}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[200px]">
|
<SelectTrigger>
|
||||||
<SelectValue placeholder={key} />
|
<SelectValue placeholder={key} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
import { RegexSetting, SettingsSchema } from "@/app/settings/settings";
|
import {
|
||||||
|
RegexSetting,
|
||||||
|
SettingsSchema,
|
||||||
|
} from "@/components/settings/SettingSchema";
|
||||||
|
|
||||||
export interface ClientSettings {
|
export interface ClientSettings {
|
||||||
theme: "light" | "dark";
|
theme: "light" | "dark";
|
||||||
|
|||||||
Reference in New Issue
Block a user