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/consultant/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/private_html/src/pages/consultant/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
} from 'lucide-react';

interface ConsultantProfile {
  id?: string;
  userId: string;
  // Basic Info
  name: string;
  email: string;
  title: string;
  bio: string;
  profilePicture: string;
  
  // Consulting Specific
  consultingSpecialties: string;
  industryExpertise: string;
  advisoryServiceTypes: string;
  clientSizePreferences: string;
  projectTypes: string;
  
  // Professional Details
  yearsOfExperience: number;
  totalConsultations: number;
  clientSatisfactionRate: number;
  hourlyRate: number;
  projectRate: number;
  retainerAvailable: boolean;
  
  // Contact & Location
  phone: string;
  workPhone: string;
  officeLocation: string;
  timezone: string;
  websiteUrl: string;
  linkedinUrl: string;
  
  // Settings
  isProfilePublic: boolean;
  availability: string;
  pronouns: string;
}

export default function ConsultantProfile() {
  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<ConsultantProfile>({
    userId: '',
    name: '',
    email: '',
    title: '',
    bio: '',
    profilePicture: '',
    consultingSpecialties: '',
    industryExpertise: '',
    advisoryServiceTypes: '',
    clientSizePreferences: '',
    projectTypes: '',
    yearsOfExperience: 0,
    totalConsultations: 0,
    clientSatisfactionRate: 0,
    hourlyRate: 0,
    projectRate: 0,
    retainerAvailable: false,
    phone: '',
    workPhone: '',
    officeLocation: '',
    timezone: '',
    websiteUrl: '',
    linkedinUrl: '',
    isProfilePublic: false,
    availability: '',
    pronouns: ''
  });

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

    if (session.user?.role !== 'LEGAL_CONSULTANT') {
      router.push('/');
      return;
    }

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

  const loadProfile = async () => {
    try {
      const response = await fetch('/api/consultant/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 || 'Legal Consultant',
        }));
      }
    } 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/consultant/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 ConsultantProfile, 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>Legal Consultant Profile - Legal Platform</title>
        <meta name="description" content="Manage your legal consultant 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">Legal Consultant Profile</h1>
                <p className="mt-2 text-gray-600">Manage your professional profile and consulting expertise</p>
              </div>
              <button
                onClick={() => router.push('/consultant/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., Legal Consultant, Compliance Advisor"
                    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 consulting approach, expertise, and what makes you unique..."
                  className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                />
              </div>

              {/* Consulting Expertise */}
              <div className="border-t pt-6">
                <h3 className="text-lg font-medium text-gray-900 mb-4">Consulting Expertise</h3>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Consulting Specialties</label>
                    <textarea
                      value={profile.consultingSpecialties}
                      onChange={(e) => handleInputChange('consultingSpecialties', e.target.value)}
                      rows={3}
                      placeholder="e.g., Compliance, Risk Management, Contract Review, Regulatory Affairs"
                      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">Industry Expertise</label>
                    <textarea
                      value={profile.industryExpertise}
                      onChange={(e) => handleInputChange('industryExpertise', e.target.value)}
                      rows={3}
                      placeholder="e.g., Technology, Healthcare, Finance, Manufacturing"
                      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">Advisory Service Types</label>
                    <textarea
                      value={profile.advisoryServiceTypes}
                      onChange={(e) => handleInputChange('advisoryServiceTypes', e.target.value)}
                      rows={3}
                      placeholder="e.g., Strategic Planning, Policy Development, Training, Audits"
                      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 Size Preferences</label>
                    <select
                      value={profile.clientSizePreferences}
                      onChange={(e) => handleInputChange('clientSizePreferences', e.target.value)}
                      className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
                    >
                      <option value="">Select preference</option>
                      <option value="startup">Startups & Small Business</option>
                      <option value="sme">SMEs (10-500 employees)</option>
                      <option value="enterprise">Enterprise (500+ employees)</option>
                      <option value="all">All sizes welcome</option>
                    </select>
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700">Project Types</label>
                    <textarea
                      value={profile.projectTypes}
                      onChange={(e) => handleInputChange('projectTypes', e.target.value)}
                      rows={3}
                      placeholder="e.g., Project-based consulting, Ongoing advisory, Training sessions"
                      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, Flexible scheduling available"
                      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 Consultations</label>
                    <input
                      type="number"
                      value={profile.totalConsultations}
                      onChange={(e) => handleInputChange('totalConsultations', 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">Project Rate ($)</label>
                    <input
                      type="number"
                      value={profile.projectRate}
                      onChange={(e) => handleInputChange('projectRate', 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 className="flex items-center">
                    <input
                      type="checkbox"
                      checked={profile.retainerAvailable}
                      onChange={(e) => handleInputChange('retainerAvailable', 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">
                      Retainer Agreements Available
                    </label>
                  </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 potential clients and other professionals
                    </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