T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/lavocat.quebec/private_html/src/components/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.quebec/private_html/src/components/PrivacySettingsModal.tsx
'use client';

import { useState, useEffect } from 'react';
import { useSession } from 'next-auth/react';
import { motion, AnimatePresence } from 'framer-motion';
import { X, Users, Eye, EyeOff, Shield, Lock, Settings } from 'lucide-react';

interface PrivacySettings {
  showFriends: boolean;
  showEmail: boolean;
  showPhone: boolean;
  showLocation: boolean;
  allowMessages: boolean;
  showOnlineStatus: boolean;
}

interface PrivacySettingsModalProps {
  isOpen: boolean;
  onClose: () => void;
}

const PrivacySettingsModal: React.FC<PrivacySettingsModalProps> = ({ isOpen, onClose }) => {
  const { data: session } = useSession();
  const [settings, setSettings] = useState<PrivacySettings>({
    showFriends: true,
    showEmail: false,
    showPhone: false,
    showLocation: false,
    allowMessages: true,
    showOnlineStatus: true,
  });
  const [isLoading, setIsLoading] = useState(false);
  const [message, setMessage] = useState('');

  useEffect(() => {
    if (isOpen && session?.user?.id) {
      fetchCurrentSettings();
    }
  }, [isOpen, session?.user?.id]);

  const fetchCurrentSettings = async () => {
    try {
      const response = await fetch(`/api/users/${session?.user?.id}`);
      if (response.ok) {
        const userData = await response.json();
        setSettings({
          showFriends: userData.showFriends ?? true,
          showEmail: userData.showEmail ?? false,
          showPhone: userData.showPhone ?? false,
          showLocation: userData.showLocation ?? false,
          allowMessages: userData.allowMessages ?? true,
          showOnlineStatus: userData.showOnlineStatus ?? true,
        });
      }
    } catch (error) {
      }
  };

  const handleSave = async () => {
    if (!session?.user?.id) return;

    setIsLoading(true);
    setMessage('');

    try {
      const response = await fetch(`/api/users/${session.user.id}`, {
        method: 'PATCH',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(settings),
      });

      if (response.ok) {
        setMessage('Privacy settings updated successfully!');
        setTimeout(() => setMessage(''), 3000);
      } else {
        setMessage('Failed to update privacy settings. Please try again.');
      }
    } catch (error) {
      setMessage('An error occurred. Please try again.');
    } finally {
      setIsLoading(false);
    }
  };

  const toggleSetting = (key: keyof PrivacySettings) => {
    setSettings(prev => ({
      ...prev,
      [key]: !prev[key],
    }));
  };

  const privacyOptions = [
    {
      key: 'showFriends' as keyof PrivacySettings,
      label: 'Show Friends List',
      description: 'Allow others to see your friends and connections',
      icon: Users,
      category: 'Profile Visibility',
    },
    {
      key: 'showEmail' as keyof PrivacySettings,
      label: 'Show Email Address',
      description: 'Display your email address on your profile',
      icon: Eye,
      category: 'Contact Information',
    },
    {
      key: 'showPhone' as keyof PrivacySettings,
      label: 'Show Phone Number',
      description: 'Display your phone number on your profile',
      icon: Eye,
      category: 'Contact Information',
    },
    {
      key: 'showLocation' as keyof PrivacySettings,
      label: 'Show Location',
      description: 'Display your location on your profile',
      icon: Eye,
      category: 'Profile Visibility',
    },
    {
      key: 'allowMessages' as keyof PrivacySettings,
      label: 'Allow Direct Messages',
      description: 'Let other users send you private messages',
      icon: Lock,
      category: 'Communication',
    },
    {
      key: 'showOnlineStatus' as keyof PrivacySettings,
      label: 'Show Online Status',
      description: 'Display when you are online',
      icon: Eye,
      category: 'Profile Visibility',
    },
  ];

  const groupedOptions = privacyOptions.reduce((acc, option) => {
    if (!acc[option.category]) {
      acc[option.category] = [];
    }
    acc[option.category].push(option);
    return acc;
  }, {} as Record<string, typeof privacyOptions>);

  return (
    <AnimatePresence>
      {isOpen && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
          <motion.div
            initial={{ opacity: 0, scale: 0.95 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.95 }}
            className="bg-white rounded-xl shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-hidden"
          >
            {/* Header */}
            <div className="flex items-center justify-between p-6 border-b border-gray-200">
              <div className="flex items-center gap-3">
                <div className="p-2 bg-blue-100 rounded-lg">
                  <Settings className="h-6 w-6 text-blue-600" />
                </div>
                <div>
                  <h2 className="text-xl font-semibold text-gray-900">Privacy Settings</h2>
                  <p className="text-sm text-gray-500">Control who can see your information</p>
                </div>
              </div>
              <button
                onClick={onClose}
                className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
              >
                <X className="h-5 w-5 text-gray-500" />
              </button>
            </div>

            {/* Content */}
            <div className="p-6 overflow-y-auto max-h-[60vh]">
              {message && (
                <div className={`mb-4 p-3 rounded-lg text-sm ${
                  message.includes('successfully') 
                    ? 'bg-green-50 text-green-700 border border-green-200' 
                    : 'bg-red-50 text-red-700 border border-red-200'
                }`}>
                  {message}
                </div>
              )}

              <div className="space-y-6">
                {Object.entries(groupedOptions).map(([category, options]) => (
                  <div key={category}>
                    <h3 className="text-lg font-medium text-gray-900 mb-3 flex items-center gap-2">
                      <Shield className="h-5 w-5 text-gray-600" />
                      {category}
                    </h3>
                    <div className="space-y-3">
                      {options.map((option) => {
                        const Icon = option.icon;
                        return (
                          <div
                            key={option.key}
                            className="flex items-center justify-between p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
                          >
                            <div className="flex items-start gap-3 flex-1">
                              <div className="p-2 bg-gray-100 rounded-lg">
                                <Icon className="h-4 w-4 text-gray-600" />
                              </div>
                              <div className="flex-1">
                                <h4 className="font-medium text-gray-900">{option.label}</h4>
                                <p className="text-sm text-gray-500 mt-1">{option.description}</p>
                              </div>
                            </div>
                              <button
                                onClick={() => toggleSetting(option.key)}
                                className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ${
                                  settings[option.key] ? 'bg-blue-600' : 'bg-gray-200'
                                }`}
                              >
                                <span
                                  className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                                    settings[option.key] ? 'translate-x-6' : 'translate-x-1'
                                  }`}
                                />
                              </button>
                          </div>
                        );
                      })}
                    </div>
                  </div>
                ))}
              </div>
            </div>

            {/* Footer */}
            <div className="flex items-center justify-end gap-3 p-6 border-t border-gray-200 bg-gray-50">
              <button
                onClick={onClose}
                className="px-4 py-2 text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
              >
                Cancel
              </button>
              <button
                onClick={handleSave}
                disabled={isLoading}
                className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
              >
                {isLoading ? (
                  <>
                    <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
                    Saving...
                  </>
                ) : (
                  'Save Changes'
                )}
              </button>
            </div>
          </motion.div>
        </div>
      )}
    </AnimatePresence>
  );
};

export default PrivacySettingsModal; 

CasperSecurity Mini