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';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import api from '@/services/api';
|
||||
|
||||
interface PrivacySetting {
|
||||
id: string;
|
||||
@@ -22,48 +24,100 @@ interface PrivacyFormProps {
|
||||
onDeleteAccount?: () => void;
|
||||
}
|
||||
|
||||
export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
|
||||
const [privacySettings, setPrivacySettings] = useState<PrivacySetting[]>([
|
||||
{
|
||||
id: 'profile_visibility',
|
||||
label: 'Profile Visibility',
|
||||
description: 'Control who can see your profile',
|
||||
value: 'public',
|
||||
options: [
|
||||
{ value: 'public', label: 'Public' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'Private' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'contact_info',
|
||||
label: 'Contact Information',
|
||||
description: 'Control who can see your contact details',
|
||||
value: 'connections',
|
||||
options: [
|
||||
{ value: 'public', label: 'Public' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'Hidden' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'activity_status',
|
||||
label: 'Activity Status',
|
||||
description: 'Show when you are active on the platform',
|
||||
value: 'public',
|
||||
options: [
|
||||
{ value: 'public', label: 'Everyone' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'No One' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
// Default privacy settings
|
||||
const DEFAULT_PRIVACY_SETTINGS: PrivacySetting[] = [
|
||||
{
|
||||
id: 'profile_visibility',
|
||||
label: 'Profile Visibility',
|
||||
description: 'Control who can see your profile',
|
||||
value: 'public',
|
||||
options: [
|
||||
{ value: 'public', label: 'Public' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'Private' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'contact_info',
|
||||
label: 'Contact Information',
|
||||
description: 'Control who can see your contact details',
|
||||
value: 'connections',
|
||||
options: [
|
||||
{ value: 'public', label: 'Public' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'Hidden' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'activity_status',
|
||||
label: 'Activity Status',
|
||||
description: 'Show when you are active on the platform',
|
||||
value: 'public',
|
||||
options: [
|
||||
{ value: 'public', label: 'Everyone' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'No One' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const [dataSettings, setDataSettings] = useState({
|
||||
shareAnalytics: true,
|
||||
personalizedAds: false,
|
||||
thirdPartySharing: false,
|
||||
});
|
||||
const DEFAULT_DATA_SETTINGS = {
|
||||
shareAnalytics: false,
|
||||
personalizedAds: 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) => {
|
||||
setPrivacySettings((prev) =>
|
||||
@@ -75,11 +129,39 @@ export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
|
||||
setDataSettings((prev) => ({ ...prev, [key]: !prev[key] }));
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
if (onSave) {
|
||||
onSave({ privacySettings, dataSettings });
|
||||
} else {
|
||||
console.log('Saving privacy settings:', { privacySettings, dataSettings });
|
||||
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) {
|
||||
onSave({ 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>
|
||||
);
|
||||
|
||||
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>
|
||||
)}
|
||||
|
||||
{/* Privacy Settings */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4">
|
||||
<div className="mb-6">
|
||||
@@ -251,9 +355,10 @@ export function PrivacyForm({ onSave, onDeleteAccount }: PrivacyFormProps) {
|
||||
<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