diff --git a/app/(app)/profile/page.tsx b/app/(app)/profile/page.tsx new file mode 100644 index 0000000..9e3942f --- /dev/null +++ b/app/(app)/profile/page.tsx @@ -0,0 +1,147 @@ +"use client"; + +import { useState } from "react"; +import { useMutation } from "@tanstack/react-query"; +import { useAuth } from "@/contexts/AuthContext"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card"; +import { Button } from "@/components/ui/Button"; +import { Input } from "@/components/ui/Input"; +import { User, Lock } from "lucide-react"; +import api from "@/lib/api"; +import { toast } from "sonner"; + +export default function ProfilePage() { + const { user } = useAuth(); + + const [infoForm, setInfoForm] = useState({ + firstName: (user as any)?.firstName ?? user?.name?.split(" ")[0] ?? "", + lastName: (user as any)?.lastName ?? user?.name?.split(" ").slice(1).join(" ") ?? "", + email: user?.email ?? "", + }); + + const [pwForm, setPwForm] = useState({ + currentPassword: "", + newPassword: "", + confirmPassword: "", + }); + + const updateInfo = useMutation({ + mutationFn: async () => { + await api.patch("/api/v1/auth/me", { + firstName: infoForm.firstName, + lastName: infoForm.lastName, + email: infoForm.email, + }); + }, + onSuccess: () => toast.success("Profile updated!"), + onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed to update profile"), + }); + + const resetPassword = useMutation({ + mutationFn: async () => { + if (pwForm.newPassword !== pwForm.confirmPassword) { + throw new Error("Passwords do not match"); + } + await api.post("/api/v1/auth/change-password", { + currentPassword: pwForm.currentPassword, + newPassword: pwForm.newPassword, + }); + }, + onSuccess: () => { + toast.success("Password changed successfully!"); + setPwForm({ currentPassword: "", newPassword: "", confirmPassword: "" }); + }, + onError: (e: any) => toast.error(e.response?.data?.message ?? e.message ?? "Failed to change password"), + }); + + return ( +
+
+

My Profile

+

Manage your account settings

+
+ + {/* Profile Info */} + + + + + Personal Information + + + +
+ setInfoForm(f => ({ ...f, firstName: e.target.value }))} + /> + setInfoForm(f => ({ ...f, lastName: e.target.value }))} + /> +
+ setInfoForm(f => ({ ...f, email: e.target.value }))} + /> +
+ +
+
+
+ + {/* Change Password */} + + + + + Change Password + + + + setPwForm(f => ({ ...f, currentPassword: e.target.value }))} + /> + setPwForm(f => ({ ...f, newPassword: e.target.value }))} + hint="Minimum 8 characters" + /> + setPwForm(f => ({ ...f, confirmPassword: e.target.value }))} + /> + {pwForm.newPassword && pwForm.confirmPassword && pwForm.newPassword !== pwForm.confirmPassword && ( +

Passwords do not match

+ )} +
+ +
+
+
+
+ ); +}