feat: Integrate API for privacy settings, enabling dynamic fetching, saving, and displaying loading/error/success states.

This commit is contained in:
pradeepkumar
2026-02-09 01:00:32 +05:30
parent 3d44892738
commit 927c185f92

View File

@@ -1,6 +1,8 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState, useEffect, useCallback } from 'react';
import { useSession } from 'next-auth/react';
import api from '@/services/api';
interface PrivacySetting { interface PrivacySetting {
id: string; id: string;
@@ -22,8 +24,8 @@ interface PrivacyFormProps {
onDeleteAccount?: () => void; onDeleteAccount?: () => void;
} }
export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) { // Default privacy settings
const [privacySettings, setPrivacySettings] = useState<PrivacySetting[]>([ const DEFAULT_PRIVACY_SETTINGS: PrivacySetting[] = [
{ {
id: 'profile_visibility', id: 'profile_visibility',
label: 'Profile Visibility', label: 'Profile Visibility',
@@ -57,13 +59,65 @@ export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
{ value: 'private', label: 'No One' }, { value: 'private', label: 'No One' },
], ],
}, },
]); ];
const [dataSettings, setDataSettings] = useState({ const DEFAULT_DATA_SETTINGS = {
shareAnalytics: true, shareAnalytics: false,
personalizedAds: false, personalizedAds: false,
thirdPartySharing: false, thirdPartySharing: false,
}); };
export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
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 [privacySettings, setPrivacySettings] = useState<PrivacySetting[]>(DEFAULT_PRIVACY_SETTINGS);
const [dataSettings, setDataSettings] = useState(DEFAULT_DATA_SETTINGS);
// 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/privacy' : '/users/preferences/privacy';
const response = await api.get(endpoint);
const savedPrefs = response.data?.data || response.data || {};
// Merge saved privacy settings with defaults
if (savedPrefs.privacySettings) {
setPrivacySettings((prev) =>
prev.map((item) => ({
...item,
value: savedPrefs.privacySettings[item.id] ?? item.value,
}))
);
}
// Merge saved data settings with defaults
if (savedPrefs.dataSettings) {
setDataSettings((prev) => ({
shareAnalytics: savedPrefs.dataSettings.shareAnalytics ?? prev.shareAnalytics,
personalizedAds: savedPrefs.dataSettings.personalizedAds ?? prev.personalizedAds,
thirdPartySharing: savedPrefs.dataSettings.thirdPartySharing ?? prev.thirdPartySharing,
}));
}
} catch (err) {
// If no saved preferences, use defaults
console.log('No saved privacy preferences found, using defaults');
} finally {
setIsLoading(false);
}
}, [session]);
useEffect(() => {
fetchPreferences();
}, [fetchPreferences]);
const handlePrivacyChange = (id: string, value: string) => { const handlePrivacyChange = (id: string, value: string) => {
setPrivacySettings((prev) => setPrivacySettings((prev) =>
@@ -75,11 +129,39 @@ export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
setDataSettings((prev) => ({ ...prev, [key]: !prev[key] })); setDataSettings((prev) => ({ ...prev, [key]: !prev[key] }));
}; };
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/privacy' : '/users/preferences/privacy';
// Transform settings to API format
const preferences = {
privacySettings: privacySettings.reduce(
(acc, item) => ({ ...acc, [item.id]: item.value }),
{} as Record<string, string>
),
dataSettings,
};
await api.put(endpoint, preferences);
setSuccess('Privacy settings saved successfully!');
if (onSave) { if (onSave) {
onSave({ privacySettings, dataSettings }); onSave({ privacySettings, dataSettings });
} else { }
console.log('Saving privacy settings:', { privacySettings, dataSettings });
// 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 privacy settings. Please try again.');
} finally {
setIsSaving(false);
} }
}; };
@@ -114,8 +196,30 @@ export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
</button> </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 ( 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>
)}
{/* Privacy Settings */} {/* Privacy Settings */}
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4"> <div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4">
<div className="mb-6"> <div className="mb-6">
@@ -251,9 +355,10 @@ export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
<div className="flex justify-end"> <div className="flex justify-end">
<button <button
onClick={handleSave} 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> </button>
</div> </div>
</> </>