diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx new file mode 100644 index 0000000..b8d6cf1 --- /dev/null +++ b/src/app/profile/page.tsx @@ -0,0 +1,222 @@ +"use client"; + +import { useSession } from "@/lib/auth-client"; +import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Separator } from "@/components/ui/separator"; +import { Mail, Calendar, User, Shield, ArrowLeft } from "lucide-react"; +import { useRouter } from "next/navigation"; + +export default function ProfilePage() { + const { data: session, isPending } = useSession(); + const router = useRouter(); + + if (isPending) { + return ( +
+
Loading...
+
+ ); + } + + if (!session) { + router.push("/"); + return null; + } + + const user = session.user; + const createdDate = user.createdAt ? new Date(user.createdAt).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }) : null; + + return ( +
+
+ +

Your Profile

+
+ +
+ {/* Profile Overview Card */} + + +
+ + + + {( + user.name?.[0] || + user.email?.[0] || + "U" + ).toUpperCase()} + + +
+

{user.name}

+
+ + {user.email} + {user.emailVerified && ( + + + Verified + + )} +
+ {createdDate && ( +
+ + Member since {createdDate} +
+ )} +
+
+
+
+ + {/* Account Information */} + + + Account Information + + Your account details and settings + + + +
+
+ +
+ {user.name || "Not provided"} +
+
+
+ +
+ {user.email} + {user.emailVerified && ( + + Verified + + )} +
+
+
+ + + +
+

Account Status

+
+
+
+

Email Verification

+

+ Email address verification status +

+
+ + {user.emailVerified ? "Verified" : "Unverified"} + +
+
+
+

Account Type

+

+ Your account access level +

+
+ Standard +
+
+
+
+
+ + {/* Account Activity */} + + + Recent Activity + + Your recent account activity and sessions + + + +
+
+
+
+
+

Current Session

+

Active now

+
+
+ + Active + +
+
+
+
+ + {/* Quick Actions */} + + + Quick Actions + + Manage your account settings and preferences + + + +
+ + + +
+

+ Additional profile management features coming soon. +

+
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/components/auth/user-profile.tsx b/src/components/auth/user-profile.tsx index 56fecf4..00556d0 100644 --- a/src/components/auth/user-profile.tsx +++ b/src/components/auth/user-profile.tsx @@ -1,12 +1,23 @@ "use client"; -import { useSession } from "@/lib/auth-client"; +import { useSession, signOut } from "@/lib/auth-client"; import { SignInButton } from "./sign-in-button"; -import { SignOutButton } from "./sign-out-button"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { User, LogOut } from "lucide-react"; export function UserProfile() { const { data: session, isPending } = useSession(); + const router = useRouter(); if (isPending) { return
Loading...
; @@ -20,26 +31,54 @@ export function UserProfile() { ); } + const handleSignOut = async () => { + await signOut(); + router.replace("/"); + router.refresh(); + }; + return ( -
- - Welcome {session.user?.name} - - - - - {( - session.user?.name?.[0] || - session.user?.email?.[0] || - "U" - ).toUpperCase()} - - - -
+ + + + + + {( + session.user?.name?.[0] || + session.user?.email?.[0] || + "U" + ).toUpperCase()} + + + + + +
+

+ {session.user?.name} +

+

+ {session.user?.email} +

+
+
+ + + + + Your Profile + + + + + + Log out + +
+
); } diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx new file mode 100644 index 0000000..12daad7 --- /dev/null +++ b/src/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } \ No newline at end of file diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx new file mode 100644 index 0000000..938aa22 --- /dev/null +++ b/src/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } \ No newline at end of file diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx new file mode 100644 index 0000000..4f1321d --- /dev/null +++ b/src/components/ui/separator.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +interface SeparatorProps extends React.HTMLAttributes { + orientation?: "horizontal" | "vertical" +} + +const Separator = React.forwardRef( + ({ className, orientation = "horizontal", ...props }, ref) => ( +
+ ) +) +Separator.displayName = "Separator" + +export { Separator } \ No newline at end of file