feat: Integrate API for fetching and saving user notification preferences, including loading, error, and success states.

This commit is contained in:
pradeepkumar
2026-02-09 00:34:02 +05:30
parent eefc4bcd78
commit 3d44892738

View File

@@ -1,6 +1,8 @@
'use client';
import { useState } from 'react';
import { useState, useEffect, useCallback } from 'react';
import { useSession } from 'next-auth/react';
import api from '@/services/api';
interface NotificationSetting {
id: string;
@@ -16,25 +18,25 @@ interface NotificationsFormProps {
}) => void;
}
export function NotificationsForm({ onSave }: NotificationsFormProps) {
const [emailNotifications, setEmailNotifications] = useState<NotificationSetting[]>([
// Default notification settings (all disabled by default)
const DEFAULT_EMAIL_NOTIFICATIONS: NotificationSetting[] = [
{
id: 'new_leads',
label: 'New Leads',
description: 'Get notified when you receive new leads',
enabled: true,
enabled: false,
},
{
id: 'messages',
label: 'Messages',
description: 'Get notified when you receive new messages',
enabled: true,
enabled: false,
},
{
id: 'connection_requests',
label: 'Connection Requests',
description: 'Get notified about new connection requests',
enabled: true,
enabled: false,
},
{
id: 'property_updates',
@@ -48,20 +50,20 @@ export function NotificationsForm({ onSave }: NotificationsFormProps) {
description: 'Receive marketing emails and promotions',
enabled: false,
},
]);
];
const [pushNotifications, setPushNotifications] = useState<NotificationSetting[]>([
const DEFAULT_PUSH_NOTIFICATIONS: NotificationSetting[] = [
{
id: 'push_messages',
label: 'Messages',
description: 'Push notifications for new messages',
enabled: true,
enabled: false,
},
{
id: 'push_leads',
label: 'New Leads',
description: 'Push notifications for new leads',
enabled: true,
enabled: false,
},
{
id: 'push_reminders',
@@ -69,7 +71,59 @@ export function NotificationsForm({ onSave }: NotificationsFormProps) {
description: 'Push notifications for scheduled reminders',
enabled: false,
},
]);
];
export function NotificationsForm({ onSave }: NotificationsFormProps) {
const { data: session } = useSession();
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
const [emailNotifications, setEmailNotifications] = useState<NotificationSetting[]>(DEFAULT_EMAIL_NOTIFICATIONS);
const [pushNotifications, setPushNotifications] = useState<NotificationSetting[]>(DEFAULT_PUSH_NOTIFICATIONS);
// Fetch saved preferences on mount
const fetchPreferences = useCallback(async () => {
if (!session) return;
try {
setIsLoading(true);
const role = (session?.user as any)?.role;
const endpoint = role === 'AGENT' ? '/agents/preferences/notifications' : '/users/preferences/notifications';
const response = await api.get(endpoint);
const savedPrefs = response.data?.data || response.data || {};
// Merge saved preferences with defaults
if (savedPrefs.email) {
setEmailNotifications((prev) =>
prev.map((item) => ({
...item,
enabled: savedPrefs.email[item.id] ?? item.enabled,
}))
);
}
if (savedPrefs.push) {
setPushNotifications((prev) =>
prev.map((item) => ({
...item,
enabled: savedPrefs.push[item.id] ?? item.enabled,
}))
);
}
} catch (err) {
// If no saved preferences, use defaults (all disabled)
console.log('No saved notification preferences found, using defaults');
} finally {
setIsLoading(false);
}
}, [session]);
useEffect(() => {
fetchPreferences();
}, [fetchPreferences]);
const toggleEmailNotification = (id: string) => {
setEmailNotifications((prev) =>
@@ -87,14 +141,36 @@ export function NotificationsForm({ onSave }: NotificationsFormProps) {
);
};
const handleSave = () => {
const handleSave = async () => {
setIsSaving(true);
setError(null);
setSuccess(null);
try {
const role = (session?.user as any)?.role;
const endpoint = role === 'AGENT' ? '/agents/preferences/notifications' : '/users/preferences/notifications';
// Transform settings to API format
const preferences = {
email: emailNotifications.reduce((acc, item) => ({ ...acc, [item.id]: item.enabled }), {}),
push: pushNotifications.reduce((acc, item) => ({ ...acc, [item.id]: item.enabled }), {}),
};
await api.put(endpoint, preferences);
setSuccess('Notification preferences saved successfully!');
if (onSave) {
onSave({ emailNotifications, pushNotifications });
} else {
console.log('Saving notification settings:', {
emailNotifications,
pushNotifications,
});
}
// Clear success message after 3 seconds
setTimeout(() => setSuccess(null), 3000);
} catch (err: unknown) {
const error = err as { response?: { data?: { message?: string } } };
setError(error.response?.data?.message || 'Failed to save notification preferences. Please try again.');
} finally {
setIsSaving(false);
}
};
@@ -119,8 +195,30 @@ export function NotificationsForm({ onSave }: NotificationsFormProps) {
</button>
);
if (isLoading) {
return (
<div className="flex items-center justify-center py-12">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#e58625]"></div>
</div>
);
}
return (
<>
{/* Error Message */}
{error && (
<div className="mb-4 p-3 bg-red-50 border border-red-200 rounded-[10px] text-red-700 text-[13px] font-serif">
{error}
</div>
)}
{/* Success Message */}
{success && (
<div className="mb-4 p-3 bg-green-50 border border-green-200 rounded-[10px] text-green-700 text-[13px] font-serif">
{success}
</div>
)}
{/* Email Notifications */}
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4">
<div className="mb-6">
@@ -193,9 +291,10 @@ export function NotificationsForm({ onSave }: NotificationsFormProps) {
<div className="flex justify-end">
<button
onClick={handleSave}
className="px-8 py-3 bg-[#e58625] text-white rounded-[15px] font-fractul font-medium text-[14px] hover:bg-[#d47920] transition-colors"
disabled={isSaving}
className="px-8 py-3 bg-[#e58625] text-white rounded-[15px] font-fractul font-medium text-[14px] hover:bg-[#d47920] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
Save Changes
{isSaving ? 'Saving...' : 'Save Changes'}
</button>
</div>
</>