mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: enhance user account management with password and profile updates
- Added validation for user profile and password update forms using Yup. - Implemented user feedback for successful profile and password updates, including prompts to re-login. - Improved UI for profile editing and password change sections, enhancing user experience. - Updated password update service to include response metadata handling.
This commit is contained in:
parent
943ceff813
commit
79a31dd8ec
4 changed files with 352 additions and 132 deletions
|
|
@ -1,61 +1,134 @@
|
|||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { updatePassword } from '@services/settings/password'
|
||||
import { Formik, Form, Field } from 'formik'
|
||||
import { Formik, Form } from 'formik'
|
||||
import React, { useEffect } from 'react'
|
||||
import { AlertTriangle } from 'lucide-react'
|
||||
import { Input } from "@components/ui/input"
|
||||
import { Button } from "@components/ui/button"
|
||||
import { Label } from "@components/ui/label"
|
||||
import { toast } from 'react-hot-toast'
|
||||
import { signOut } from 'next-auth/react'
|
||||
import { getUriWithoutOrg } from '@services/config/config'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
old_password: Yup.string().required('Current password is required'),
|
||||
new_password: Yup.string()
|
||||
.required('New password is required')
|
||||
.min(8, 'Password must be at least 8 characters'),
|
||||
})
|
||||
|
||||
function UserEditPassword() {
|
||||
const session = useLHSession() as any
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
|
||||
const updatePasswordUI = async (values: any) => {
|
||||
let user_id = session.data.user.id
|
||||
await updatePassword(user_id, values, access_token)
|
||||
const loadingToast = toast.loading('Updating password...')
|
||||
try {
|
||||
let user_id = session.data.user.id
|
||||
const response = await updatePassword(user_id, values, access_token)
|
||||
|
||||
if (response.success) {
|
||||
toast.dismiss(loadingToast)
|
||||
|
||||
// Show success message and notify about logout
|
||||
toast.success('Password updated successfully', { duration: 4000 })
|
||||
toast((t) => (
|
||||
<div className="flex items-center gap-2">
|
||||
<span>Please login again with your new password</span>
|
||||
</div>
|
||||
), {
|
||||
duration: 4000,
|
||||
icon: '🔑'
|
||||
})
|
||||
|
||||
// Wait for 4 seconds before signing out
|
||||
await new Promise(resolve => setTimeout(resolve, 4000))
|
||||
signOut({ redirect: true, callbackUrl: getUriWithoutOrg('/') })
|
||||
} else {
|
||||
toast.error(response.data.detail || 'Failed to update password', { id: loadingToast })
|
||||
}
|
||||
} catch (error: any) {
|
||||
const errorMessage = error.data?.detail || 'Failed to update password. Please try again.'
|
||||
toast.error(errorMessage, { id: loadingToast })
|
||||
console.error('Password update error:', error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => { }, [session])
|
||||
|
||||
return (
|
||||
<div className="ml-10 mr-10 mx-auto bg-white rounded-xl shadow-sm px-6 py-5">
|
||||
<Formik
|
||||
initialValues={{ old_password: '', new_password: '' }}
|
||||
enableReinitialize
|
||||
onSubmit={(values, { setSubmitting }) => {
|
||||
setTimeout(() => {
|
||||
setSubmitting(false)
|
||||
updatePasswordUI(values)
|
||||
}, 400)
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting }) => (
|
||||
<Form className="max-w-md">
|
||||
<label className="block mb-2 font-bold" htmlFor="old_password">
|
||||
Old Password
|
||||
</label>
|
||||
<Field
|
||||
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
type="password"
|
||||
name="old_password"
|
||||
/>
|
||||
<div className="sm:mx-10 mx-0 bg-white rounded-xl nice-shadow">
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col bg-gray-50 -space-y-1 px-5 py-3 mx-3 my-3 rounded-md">
|
||||
<h1 className="font-bold text-xl text-gray-800">
|
||||
Change Password
|
||||
</h1>
|
||||
<h2 className="text-gray-500 text-md">
|
||||
Update your password to keep your account secure
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<label className="block mb-2 font-bold" htmlFor="new_password">
|
||||
New Password
|
||||
</label>
|
||||
<Field
|
||||
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
type="password"
|
||||
name="new_password"
|
||||
/>
|
||||
<div className="px-8 py-6">
|
||||
<Formik
|
||||
initialValues={{ old_password: '', new_password: '' }}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={(values, { setSubmitting }) => {
|
||||
setTimeout(() => {
|
||||
setSubmitting(false)
|
||||
updatePasswordUI(values)
|
||||
}, 400)
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting, handleChange, errors, touched }) => (
|
||||
<Form className="w-full max-w-2xl mx-auto space-y-6">
|
||||
<div>
|
||||
<Label htmlFor="old_password">Current Password</Label>
|
||||
<Input
|
||||
type="password"
|
||||
id="old_password"
|
||||
name="old_password"
|
||||
onChange={handleChange}
|
||||
className="mt-1"
|
||||
/>
|
||||
{touched.old_password && errors.old_password && (
|
||||
<p className="text-red-500 text-sm mt-1">{errors.old_password}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="px-6 py-3 text-white bg-black rounded-lg shadow-md hover:bg-black focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
<div>
|
||||
<Label htmlFor="new_password">New Password</Label>
|
||||
<Input
|
||||
type="password"
|
||||
id="new_password"
|
||||
name="new_password"
|
||||
onChange={handleChange}
|
||||
className="mt-1"
|
||||
/>
|
||||
{touched.new_password && errors.new_password && (
|
||||
<p className="text-red-500 text-sm mt-1">{errors.new_password}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2 text-amber-600 bg-amber-50 p-3 rounded-md">
|
||||
<AlertTriangle size={16} />
|
||||
<span className="text-sm">You will be logged out after changing your password</span>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end pt-2">
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="bg-black text-white hover:bg-black/90"
|
||||
>
|
||||
{isSubmitting ? 'Updating...' : 'Update Password'}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue