Theme toggle, notifications popover, command palette (Cmd+K), user account dropdown with settings modal, subtle sidebar active states, and nav transition animation.
132 lines
4.3 KiB
TypeScript
Executable File
132 lines
4.3 KiB
TypeScript
Executable File
"use client"
|
|
|
|
import * as React from "react"
|
|
import { IconCamera } from "@tabler/icons-react"
|
|
|
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
|
import { Button } from "@/components/ui/button"
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "@/components/ui/dialog"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Label } from "@/components/ui/label"
|
|
import { Separator } from "@/components/ui/separator"
|
|
|
|
export function AccountModal({
|
|
open,
|
|
onOpenChange,
|
|
}: {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
}) {
|
|
const [name, setName] = React.useState("Martine Vogel")
|
|
const [email, setEmail] = React.useState("martine@compass.io")
|
|
const [currentPassword, setCurrentPassword] = React.useState("")
|
|
const [newPassword, setNewPassword] = React.useState("")
|
|
const [confirmPassword, setConfirmPassword] = React.useState("")
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-md">
|
|
<DialogHeader>
|
|
<DialogTitle>Account Settings</DialogTitle>
|
|
<DialogDescription>
|
|
Manage your profile and security settings.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="space-y-6 py-2">
|
|
<div className="flex items-center gap-4">
|
|
<div className="relative">
|
|
<Avatar className="size-16">
|
|
<AvatarImage src="/avatars/martine.jpg" alt={name} />
|
|
<AvatarFallback>MV</AvatarFallback>
|
|
</Avatar>
|
|
<button className="bg-primary text-primary-foreground absolute -right-1 -bottom-1 flex size-6 items-center justify-center rounded-full">
|
|
<IconCamera className="size-3.5" />
|
|
</button>
|
|
</div>
|
|
<div>
|
|
<p className="font-medium">{name}</p>
|
|
<p className="text-muted-foreground text-sm">{email}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
<div className="space-y-4">
|
|
<h4 className="text-sm font-medium">Profile</h4>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="name">Name</Label>
|
|
<Input
|
|
id="name"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="email">Email</Label>
|
|
<Input
|
|
id="email"
|
|
type="email"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
<div className="space-y-4">
|
|
<h4 className="text-sm font-medium">Change Password</h4>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="current-password">Current Password</Label>
|
|
<Input
|
|
id="current-password"
|
|
type="password"
|
|
value={currentPassword}
|
|
onChange={(e) => setCurrentPassword(e.target.value)}
|
|
placeholder="Enter current password"
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="new-password">New Password</Label>
|
|
<Input
|
|
id="new-password"
|
|
type="password"
|
|
value={newPassword}
|
|
onChange={(e) => setNewPassword(e.target.value)}
|
|
placeholder="Enter new password"
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="confirm-password">Confirm Password</Label>
|
|
<Input
|
|
id="confirm-password"
|
|
type="password"
|
|
value={confirmPassword}
|
|
onChange={(e) => setConfirmPassword(e.target.value)}
|
|
placeholder="Confirm new password"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
Cancel
|
|
</Button>
|
|
<Button onClick={() => onOpenChange(false)}>
|
|
Save Changes
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|