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