Refactor admin navigation and header components to update links for dashboard, booking, and notifications to include the '/admin' prefix. Remove unused booking, dashboard, notifications, and user dashboard pages to streamline the admin panel. Enhance N… #12

Merged
David merged 1 commits from feat/book-now into master 2025-11-12 21:54:57 +00:00
12 changed files with 716 additions and 29 deletions
Showing only changes of commit d9ddfee0cf - Show all commits

View File

@ -53,7 +53,7 @@ export function Header() {
<div className="px-3 sm:px-4 md:px-6 lg:px-8"> <div className="px-3 sm:px-4 md:px-6 lg:px-8">
<div className="flex items-center justify-between h-14 sm:h-16"> <div className="flex items-center justify-between h-14 sm:h-16">
{/* Logo */} {/* Logo */}
<Link href="/dashboard" className="flex items-center gap-2 sm:gap-3"> <Link href="/admin/dashboard" className="flex items-center gap-2 sm:gap-3">
<div className="flex items-center justify-center w-8 h-8 sm:w-10 sm:h-10 rounded-lg bg-linear-to-r from-rose-100 to-pink-100"> <div className="flex items-center justify-center w-8 h-8 sm:w-10 sm:h-10 rounded-lg bg-linear-to-r from-rose-100 to-pink-100">
<Heart className="w-4 h-4 sm:w-6 sm:h-6 text-rose-600" fill="currentColor" /> <Heart className="w-4 h-4 sm:w-6 sm:h-6 text-rose-600" fill="currentColor" />
</div> </div>
@ -63,9 +63,9 @@ export function Header() {
{/* Navigation Links */} {/* Navigation Links */}
<nav className="flex items-center gap-0.5 sm:gap-1"> <nav className="flex items-center gap-0.5 sm:gap-1">
<Link <Link
href="/dashboard" href="/admin/dashboard"
className={`flex items-center gap-1 sm:gap-2 px-2 sm:px-3 md:px-4 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-colors ${ className={`flex items-center gap-1 sm:gap-2 px-2 sm:px-3 md:px-4 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-colors ${
pathname === "/dashboard" pathname === "/admin/dashboard"
? "bg-linear-to-r from-rose-500 to-pink-600 text-white" ? "bg-linear-to-r from-rose-500 to-pink-600 text-white"
: "text-gray-600 hover:bg-gray-100" : "text-gray-600 hover:bg-gray-100"
}`} }`}
@ -74,9 +74,9 @@ export function Header() {
<span className="hidden sm:inline">Dashboard</span> <span className="hidden sm:inline">Dashboard</span>
</Link> </Link>
<Link <Link
href="/booking" href="/admin/booking"
className={`flex items-center gap-1 sm:gap-2 px-2 sm:px-3 md:px-4 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-colors ${ className={`flex items-center gap-1 sm:gap-2 px-2 sm:px-3 md:px-4 py-1.5 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-colors ${
pathname === "/booking" pathname === "/admin/booking"
? "bg-linear-to-r from-rose-500 to-pink-600 text-white" ? "bg-linear-to-r from-rose-500 to-pink-600 text-white"
: "text-gray-600 hover:bg-gray-100" : "text-gray-600 hover:bg-gray-100"
}`} }`}
@ -155,7 +155,7 @@ export function Header() {
</div> </div>
<div className="p-3 border-t bg-gray-50"> <div className="p-3 border-t bg-gray-50">
<Link <Link
href="/notifications" href="/admin/notifications"
onClick={() => setNotificationsOpen(false)} onClick={() => setNotificationsOpen(false)}
className="block w-full text-center text-sm font-medium text-rose-600 hover:text-rose-700 hover:underline transition-colors" className="block w-full text-center text-sm font-medium text-rose-600 hover:text-rose-700 hover:underline transition-colors"
> >
@ -181,7 +181,7 @@ export function Header() {
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
setUserMenuOpen(false); setUserMenuOpen(false);
// Add settings navigation here router.push("/admin/settings");
}} }}
className="w-full flex items-center gap-3 px-4 py-3 justify-start hover:bg-gray-50 transition-colors cursor-pointer" className="w-full flex items-center gap-3 px-4 py-3 justify-start hover:bg-gray-50 transition-colors cursor-pointer"
> >

View File

@ -15,8 +15,8 @@ import {
} from "lucide-react"; } from "lucide-react";
const navItems = [ const navItems = [
{ label: "Dashboard", icon: LayoutGrid, href: "/dashboard" }, { label: "Dashboard", icon: LayoutGrid, href: "/admin/dashboard" },
{ label: "Book Appointment", icon: Calendar, href: "/booking" }, { label: "Book Appointment", icon: Calendar, href: "/admin/booking" },
]; ];
export default function SideNav() { export default function SideNav() {
@ -132,16 +132,37 @@ export default function SideNav() {
{/* Bottom Actions */} {/* Bottom Actions */}
<div className="mt-auto pt-4 pb-4 border-t border-gray-200"> <div className="mt-auto pt-4 pb-4 border-t border-gray-200">
<Link <div className="relative flex items-center w-full">
href="/settings" {pathname === "/admin/settings" && (
onClick={() => setOpen(false)} <span
className="group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg" className="absolute left-0 top-0 h-[40px] w-[3px] bg-linear-to-r from-rose-500 to-pink-600"
> style={{ left: 0 }}
<Settings size={18} strokeWidth={1.5} className="text-gray-700 group-hover:text-gray-900" /> />
<span className="font-light leading-none text-[12px]" style={{ fontWeight: 300 }}> )}
Settings <Link
</span> href="/admin/settings"
</Link> onClick={() => setOpen(false)}
className={`group flex items-center gap-2 py-2.5 pl-3 md:pl-3 pr-3 md:pr-3 transition-colors duration-200 w-[90%] md:w-[90%] ml-1 md:ml-2 cursor-pointer justify-start rounded-lg ${
pathname === "/admin/settings"
? "bg-linear-to-r from-rose-500 to-pink-600 text-white border border-rose-500 rounded-[5px] shadow-sm"
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
}`}
style={pathname === "/admin/settings" ? { height: 40 } : {}}
>
<Settings
size={18}
strokeWidth={pathname === "/admin/settings" ? 2.2 : 1.5}
className={
pathname === "/admin/settings"
? "text-white"
: "text-gray-700 group-hover:text-gray-900"
}
/>
<span className="font-light leading-none text-[12px]" style={{ fontWeight: 300 }}>
Settings
</span>
</Link>
</div>
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {

View File

@ -0,0 +1,307 @@
"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
import {
User,
Mail,
Phone,
Save,
ArrowLeft,
Lock,
Eye,
EyeOff,
} from "lucide-react";
import Link from "next/link";
export default function AdminSettingsPage() {
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
fullName: "Hammond",
email: "admin@attuneheart.com",
phone: "+1 (555) 123-4567",
});
const [passwordData, setPasswordData] = useState({
currentPassword: "",
newPassword: "",
confirmPassword: "",
});
const [showPasswords, setShowPasswords] = useState({
current: false,
new: false,
confirm: false,
});
const handleInputChange = (field: string, value: string) => {
setFormData((prev) => ({
...prev,
[field]: value,
}));
};
const handlePasswordChange = (field: string, value: string) => {
setPasswordData((prev) => ({
...prev,
[field]: value,
}));
};
const togglePasswordVisibility = (field: "current" | "new" | "confirm") => {
setShowPasswords((prev) => ({
...prev,
[field]: !prev[field],
}));
};
const handleSave = async () => {
setLoading(true);
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 1000));
setLoading(false);
// In a real app, you would show a success message here
};
const handlePasswordSave = async () => {
if (passwordData.newPassword !== passwordData.confirmPassword) {
// In a real app, you would show an error message here
alert("New passwords do not match");
return;
}
if (passwordData.newPassword.length < 8) {
// In a real app, you would show an error message here
alert("Password must be at least 8 characters long");
return;
}
setLoading(true);
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 1000));
setLoading(false);
// Reset password fields
setPasswordData({
currentPassword: "",
newPassword: "",
confirmPassword: "",
});
// In a real app, you would show a success message here
};
return (
<div className="min-h-screen bg-gray-50">
{/* Main Content */}
<main className="p-4 sm:p-6 lg:p-8 space-y-6">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-4">
<Link href="/admin/dashboard">
<Button variant="ghost" size="icon" className="hover:bg-gray-100">
<ArrowLeft className="w-4 h-4" />
</Button>
</Link>
<div>
<h1 className="text-2xl font-semibold text-gray-900 mb-1">
Settings
</h1>
<p className="text-sm text-gray-600">
Manage your account settings and practice information
</p>
</div>
</div>
<Button
onClick={handleSave}
disabled={loading}
className="bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
>
{loading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
) : (
<Save className="w-4 h-4 mr-2" />
)}
Save Changes
</Button>
</div>
<div className="max-w-4xl mx-auto">
<div className="space-y-6">
{/* Profile Information */}
<Card className="bg-white border-gray-200">
<CardHeader>
<div className="flex items-center gap-2">
<User className="w-5 h-5 text-gray-600" />
<CardTitle className="text-gray-900">Profile Information</CardTitle>
</div>
<CardDescription className="text-gray-600">
Update your personal information and contact details
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Full Name
</label>
<div className="relative">
<User className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type="text"
value={formData.fullName}
onChange={(e) => handleInputChange("fullName", e.target.value)}
className="pl-10"
placeholder="Enter your full name"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Email Address
</label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type="email"
value={formData.email}
onChange={(e) => handleInputChange("email", e.target.value)}
className="pl-10"
placeholder="Enter your email"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Phone Number
</label>
<div className="relative">
<Phone className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type="tel"
value={formData.phone}
onChange={(e) => handleInputChange("phone", e.target.value)}
className="pl-10"
placeholder="Enter your phone number"
/>
</div>
</div>
</CardContent>
</Card>
{/* Change Password */}
<Card className="bg-white border-gray-200">
<CardHeader>
<div className="flex items-center gap-2">
<Lock className="w-5 h-5 text-gray-600" />
<CardTitle className="text-gray-900">Change Password</CardTitle>
</div>
<CardDescription className="text-gray-600">
Update your password to keep your account secure
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Current Password
</label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type={showPasswords.current ? "text" : "password"}
value={passwordData.currentPassword}
onChange={(e) => handlePasswordChange("currentPassword", e.target.value)}
className="pl-10 pr-10"
placeholder="Enter your current password"
/>
<button
type="button"
onClick={() => togglePasswordVisibility("current")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPasswords.current ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</button>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
New Password
</label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type={showPasswords.new ? "text" : "password"}
value={passwordData.newPassword}
onChange={(e) => handlePasswordChange("newPassword", e.target.value)}
className="pl-10 pr-10"
placeholder="Enter your new password"
/>
<button
type="button"
onClick={() => togglePasswordVisibility("new")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPasswords.new ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</button>
</div>
<p className="text-xs text-gray-500">
Password must be at least 8 characters long
</p>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Confirm New Password
</label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type={showPasswords.confirm ? "text" : "password"}
value={passwordData.confirmPassword}
onChange={(e) => handlePasswordChange("confirmPassword", e.target.value)}
className="pl-10 pr-10"
placeholder="Confirm your new password"
/>
<button
type="button"
onClick={() => togglePasswordVisibility("confirm")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPasswords.confirm ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</button>
</div>
</div>
<div className="pt-2">
<Button
onClick={handlePasswordSave}
disabled={loading || !passwordData.currentPassword || !passwordData.newPassword || !passwordData.confirmPassword}
className="bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
>
{loading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
) : (
<Lock className="w-4 h-4 mr-2" />
)}
Update Password
</Button>
</div>
</CardContent>
</Card>
</div>
</div>
</main>
</div>
);
}

8
app/(pages)/layout.tsx Normal file
View File

@ -0,0 +1,8 @@
export default function PagesLayout({ children }: { children: React.ReactNode }) {
return (
<div>
{children}
</div>
)
}

8
app/(user)/layout.tsx Normal file
View File

@ -0,0 +1,8 @@
export default function UserLayout({ children }: { children: React.ReactNode }) {
return (
<div>
{children}
</div>
)
}

View File

@ -15,6 +15,7 @@ import {
XCircle, XCircle,
CalendarCheck, CalendarCheck,
ArrowUpRight, ArrowUpRight,
Settings,
} from "lucide-react"; } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { Navbar } from "@/components/Navbar"; import { Navbar } from "@/components/Navbar";
@ -139,14 +140,25 @@ export default function UserDashboard() {
Here's an overview of your appointments Here's an overview of your appointments
</p> </p>
</div> </div>
<Link href="/book-now"> <div className="flex items-center gap-3">
<Button <Link href="/user/settings">
className="bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white" <Button
> variant="outline"
<CalendarPlus className="w-4 h-4 mr-2" /> className="hover:bg-gray-100"
Book Appointment >
</Button> <Settings className="w-4 h-4 mr-2" />
</Link> Settings
</Button>
</Link>
<Link href="/book-now">
<Button
className="bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
>
<CalendarPlus className="w-4 h-4 mr-2" />
Book Appointment
</Button>
</Link>
</div>
</div> </div>
{loading ? ( {loading ? (

View File

@ -0,0 +1,310 @@
"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
import {
User,
Mail,
Phone,
Save,
ArrowLeft,
Lock,
Eye,
EyeOff,
} from "lucide-react";
import Link from "next/link";
import { Navbar } from "@/components/Navbar";
export default function SettingsPage() {
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
fullName: "John Doe",
email: "john.doe@example.com",
phone: "+1 (555) 123-4567",
});
const [passwordData, setPasswordData] = useState({
currentPassword: "",
newPassword: "",
confirmPassword: "",
});
const [showPasswords, setShowPasswords] = useState({
current: false,
new: false,
confirm: false,
});
const handleInputChange = (field: string, value: string) => {
setFormData((prev) => ({
...prev,
[field]: value,
}));
};
const handlePasswordChange = (field: string, value: string) => {
setPasswordData((prev) => ({
...prev,
[field]: value,
}));
};
const togglePasswordVisibility = (field: "current" | "new" | "confirm") => {
setShowPasswords((prev) => ({
...prev,
[field]: !prev[field],
}));
};
const handleSave = async () => {
setLoading(true);
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 1000));
setLoading(false);
// In a real app, you would show a success message here
};
const handlePasswordSave = async () => {
if (passwordData.newPassword !== passwordData.confirmPassword) {
// In a real app, you would show an error message here
alert("New passwords do not match");
return;
}
if (passwordData.newPassword.length < 8) {
// In a real app, you would show an error message here
alert("Password must be at least 8 characters long");
return;
}
setLoading(true);
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 1000));
setLoading(false);
// Reset password fields
setPasswordData({
currentPassword: "",
newPassword: "",
confirmPassword: "",
});
// In a real app, you would show a success message here
};
return (
<div className="min-h-screen bg-gray-50">
<Navbar />
{/* Main Content */}
<main className="container mx-auto px-4 sm:px-6 lg:px-8 space-y-6 pt-20 sm:pt-24 pb-8">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-4">
<Link href="/user/dashboard">
<Button variant="ghost" size="icon" className="hover:bg-gray-100">
<ArrowLeft className="w-4 h-4" />
</Button>
</Link>
<div>
<h1 className="text-2xl font-semibold text-gray-900 mb-1">
Settings
</h1>
<p className="text-sm text-gray-600">
Manage your account settings and preferences
</p>
</div>
</div>
<Button
onClick={handleSave}
disabled={loading}
className="bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
>
{loading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
) : (
<Save className="w-4 h-4 mr-2" />
)}
Save Changes
</Button>
</div>
<div className="max-w-4xl mx-auto">
<div className="space-y-6">
{/* Profile Information */}
<Card className="bg-white border-gray-200">
<CardHeader>
<div className="flex items-center gap-2">
<User className="w-5 h-5 text-gray-600" />
<CardTitle className="text-gray-900">Profile Information</CardTitle>
</div>
<CardDescription className="text-gray-600">
Update your personal information and contact details
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Full Name
</label>
<div className="relative">
<User className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type="text"
value={formData.fullName}
onChange={(e) => handleInputChange("fullName", e.target.value)}
className="pl-10"
placeholder="Enter your full name"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Email Address
</label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type="email"
value={formData.email}
onChange={(e) => handleInputChange("email", e.target.value)}
className="pl-10"
placeholder="Enter your email"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Phone Number
</label>
<div className="relative">
<Phone className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type="tel"
value={formData.phone}
onChange={(e) => handleInputChange("phone", e.target.value)}
className="pl-10"
placeholder="Enter your phone number"
/>
</div>
</div>
</CardContent>
</Card>
{/* Change Password */}
<Card className="bg-white border-gray-200">
<CardHeader>
<div className="flex items-center gap-2">
<Lock className="w-5 h-5 text-gray-600" />
<CardTitle className="text-gray-900">Change Password</CardTitle>
</div>
<CardDescription className="text-gray-600">
Update your password to keep your account secure
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Current Password
</label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type={showPasswords.current ? "text" : "password"}
value={passwordData.currentPassword}
onChange={(e) => handlePasswordChange("currentPassword", e.target.value)}
className="pl-10 pr-10"
placeholder="Enter your current password"
/>
<button
type="button"
onClick={() => togglePasswordVisibility("current")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPasswords.current ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</button>
</div>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
New Password
</label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type={showPasswords.new ? "text" : "password"}
value={passwordData.newPassword}
onChange={(e) => handlePasswordChange("newPassword", e.target.value)}
className="pl-10 pr-10"
placeholder="Enter your new password"
/>
<button
type="button"
onClick={() => togglePasswordVisibility("new")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPasswords.new ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</button>
</div>
<p className="text-xs text-gray-500">
Password must be at least 8 characters long
</p>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-gray-700">
Confirm New Password
</label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
type={showPasswords.confirm ? "text" : "password"}
value={passwordData.confirmPassword}
onChange={(e) => handlePasswordChange("confirmPassword", e.target.value)}
className="pl-10 pr-10"
placeholder="Confirm your new password"
/>
<button
type="button"
onClick={() => togglePasswordVisibility("confirm")}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPasswords.confirm ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</button>
</div>
</div>
<div className="pt-2">
<Button
onClick={handlePasswordSave}
disabled={loading || !passwordData.currentPassword || !passwordData.newPassword || !passwordData.confirmPassword}
className="bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white"
>
{loading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
) : (
<Lock className="w-4 h-4 mr-2" />
)}
Update Password
</Button>
</div>
</CardContent>
</Card>
</div>
</div>
</main>
</div>
);
}

View File

@ -5,9 +5,13 @@ import { Button } from "@/components/ui/button";
import { Heart } from "lucide-react"; import { Heart } from "lucide-react";
import { ThemeToggle } from "@/components/ThemeToggle"; import { ThemeToggle } from "@/components/ThemeToggle";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { LoginDialog } from "@/components/LoginDialog";
import { useRouter } from "next/navigation";
export function Navbar() { export function Navbar() {
const [isDark, setIsDark] = useState(false); const [isDark, setIsDark] = useState(false);
const [loginDialogOpen, setLoginDialogOpen] = useState(false);
const router = useRouter();
useEffect(() => { useEffect(() => {
const checkTheme = () => { const checkTheme = () => {
@ -31,6 +35,11 @@ export function Navbar() {
} }
}; };
const handleLoginSuccess = () => {
// Redirect to user dashboard after successful login
router.push("/user/dashboard");
};
return ( return (
<motion.nav <motion.nav
initial={{ y: -100 }} initial={{ y: -100 }}
@ -79,8 +88,13 @@ export function Navbar() {
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button size="sm" variant="outline" className="hidden sm:inline-flex hover:opacity-90 hover:scale-105 transition-all dark:hover:bg-cyan-900/30" asChild> <Button
<a href="/login">Sign In</a> size="sm"
variant="outline"
className="hidden sm:inline-flex hover:opacity-90 hover:scale-105 transition-all dark:hover:bg-cyan-900/30"
onClick={() => setLoginDialogOpen(true)}
>
Sign In
</Button> </Button>
<ThemeToggle /> <ThemeToggle />
<Button size="sm" className="hidden sm:inline-flex hover:opacity-90 hover:scale-105 transition-all dark:hover:bg-emerald-600" asChild> <Button size="sm" className="hidden sm:inline-flex hover:opacity-90 hover:scale-105 transition-all dark:hover:bg-emerald-600" asChild>
@ -89,6 +103,13 @@ export function Navbar() {
</div> </div>
</div> </div>
</div> </div>
{/* Login Dialog */}
<LoginDialog
open={loginDialogOpen}
onOpenChange={setLoginDialogOpen}
onLoginSuccess={handleLoginSuccess}
/>
</motion.nav> </motion.nav>
); );
} }