From c3eaacce9349b7030836e0d8d72727323ef3428d Mon Sep 17 00:00:00 2001
From: pradeepkumar
Date: Fri, 6 Feb 2026 09:45:12 +0530
Subject: [PATCH] feat: Implement password change functionality with
client-side validation, API integration, and UI feedback for loading,
success, and errors.
---
.../settings/PasswordSecurityForm.tsx | 92 +++++++++++++++++--
1 file changed, 83 insertions(+), 9 deletions(-)
diff --git a/src/components/settings/PasswordSecurityForm.tsx b/src/components/settings/PasswordSecurityForm.tsx
index 5662c06..aabbf60 100644
--- a/src/components/settings/PasswordSecurityForm.tsx
+++ b/src/components/settings/PasswordSecurityForm.tsx
@@ -2,6 +2,7 @@
import { useState } from 'react';
import { TwoFactorSettings } from './TwoFactorSettings';
+import api from '@/services/api';
interface PasswordSecurityFormProps {
onSave?: (data: { currentPassword: string; newPassword: string }) => void;
@@ -20,23 +21,81 @@ export function PasswordSecurityForm({ onSave }: PasswordSecurityFormProps) {
confirm: false,
});
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState('');
+ const [success, setSuccess] = useState('');
+
const handleChange = (field: string, value: string) => {
setFormData((prev) => ({ ...prev, [field]: value }));
+ // Clear messages when user starts typing
+ if (error) setError('');
+ if (success) setSuccess('');
};
const toggleShowPassword = (field: 'current' | 'new' | 'confirm') => {
setShowPasswords((prev) => ({ ...prev, [field]: !prev[field] }));
};
- const handleSave = () => {
- if (formData.newPassword !== formData.confirmPassword) {
- alert('Passwords do not match');
+ const validatePassword = (password: string): boolean => {
+ // Minimum 8 characters with at least one uppercase, lowercase, and number
+ const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
+ return regex.test(password);
+ };
+
+ const handleSave = async () => {
+ setError('');
+ setSuccess('');
+
+ // Validate fields
+ if (!formData.currentPassword) {
+ setError('Current password is required');
return;
}
- if (onSave) {
- onSave({ currentPassword: formData.currentPassword, newPassword: formData.newPassword });
- } else {
- console.log('Updating password');
+
+ if (!formData.newPassword) {
+ setError('New password is required');
+ return;
+ }
+
+ if (!validatePassword(formData.newPassword)) {
+ setError('Password must be at least 8 characters with uppercase, lowercase, and number');
+ return;
+ }
+
+ if (formData.newPassword !== formData.confirmPassword) {
+ setError('Passwords do not match');
+ return;
+ }
+
+ setLoading(true);
+
+ try {
+ await api.post('/auth/change-password', {
+ currentPassword: formData.currentPassword,
+ newPassword: formData.newPassword,
+ });
+
+ setSuccess('Password changed successfully');
+ setFormData({
+ currentPassword: '',
+ newPassword: '',
+ confirmPassword: '',
+ });
+
+ // Call onSave callback if provided
+ if (onSave) {
+ onSave({ currentPassword: formData.currentPassword, newPassword: formData.newPassword });
+ }
+ } catch (err: unknown) {
+ const error = err as { response?: { data?: { message?: string | string[] } } };
+ const message = error.response?.data?.message;
+ if (Array.isArray(message)) {
+ setError(message[0]);
+ } else {
+ setError(message || 'Failed to change password. Please try again.');
+ }
+ } finally {
+ setLoading(false);
}
};
@@ -53,6 +112,20 @@ export function PasswordSecurityForm({ onSave }: PasswordSecurityFormProps) {
+ {/* Error Message */}
+ {error && (
+
+ {error}
+
+ )}
+
+ {/* Success Message */}
+ {success && (
+
+ {success}
+
+ )}
+
{/* Form Fields */}
{/* Current Password */}
@@ -132,9 +205,10 @@ export function PasswordSecurityForm({ onSave }: PasswordSecurityFormProps) {