feat: Integrate API for fetching and saving user notification preferences, including loading, error, and success states.
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user