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/admin/applications/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/private_html/src/pages/admin/applications/[id].tsx
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';
import LayoutWithSidebar from '@/components/LayoutWithSidebar';
import RegistrationForm from '@/components/RegistrationForm';
import { motion } from 'framer-motion';
import { getFacilityName } from '@/utils/facilities';

interface RegistrationWithDetails {
  id: string;
  firstName: string;
  lastName: string;
  email: string;
  phone: string;
  birthDate: string;
  relationship: string;
  preferredLanguage: string;
  preferredContactMethod: string;
  message?: string;
  status: 'PENDING' | 'APPROVED' | 'REJECTED';
  createdAt: string;
  updatedAt: string;
  userId: string;
  address?: {
    street: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  };
  detaineeInfo?: {
    name: string;
    facility: string;
    inmateId: string;
    incarcerationDate: string;
    expectedReleaseDate?: string;
  };
  file?: {
    name: string;
    type: string;
    url: string;
  };
}

export default function AdminApplicationView() {
  const { data: session, status } = useSession();
  const router = useRouter();
  const { id } = router.query;
  const [registration, setRegistration] = useState<RegistrationWithDetails | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [isEditing, setIsEditing] = useState(false);
  const [isFrench, setIsFrench] = useState(false);

  // Debug logging for state changes
  useEffect(() => {
    console.log('🔄 State update:', {
      loading,
      error,
      hasRegistration: !!registration,
      status,
      userRole: session?.user?.role
    });
  }, [loading, error, registration, status, session?.user?.role]);

  useEffect(() => {
    if (status === 'unauthenticated') {
      router.push('/auth/login');
      return;
    }
    // ...rest of your logic
  }, [status, router]);

  useEffect(() => {
    const fetchRegistration = async () => {
      if (!id || typeof id !== 'string') return;

      try {
        console.log('🔍 Fetching registration:', id);
        const response = await fetch(`/api/admin/registrations/${id}`);
        console.log('📡 Response status:', response.status);
        
        if (!response.ok) {
          const errorData = await response.json().catch(() => ({}));
          console.error('❌ API Error:', errorData);
          throw new Error(`Failed to fetch registration: ${response.status} ${errorData.error || ''}`);
        }
        
        const data = await response.json();
        console.log('✅ Registration data:', data);
        setRegistration(data);
      } catch (err) {
        console.error('❌ Fetch error:', err);
        setError(err instanceof Error ? err.message : 'Error loading registration');
      } finally {
        setLoading(false);
      }
    };

    if (status === 'authenticated' && ['ADMIN', 'SUPERADMIN'].includes(session?.user?.role)) {
      console.log('🔐 User authenticated with role:', session.user.role);
      fetchRegistration();
    } else {
      console.log('❌ User not authenticated or wrong role:', {
        status,
        role: session?.user?.role
      });
    }
  }, [id, status, session]);

  const handleStatusChange = async (newStatus: 'PENDING' | 'APPROVED' | 'REJECTED') => {
    if (!registration) return;

    try {
      const response = await fetch(`/api/admin/registrations/${registration.id}`, {
        method: 'PATCH',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ status: newStatus }),
      });

      if (!response.ok) {
        throw new Error('Failed to update status');
      }

      const updatedRegistration = await response.json();
      setRegistration(updatedRegistration);
    } catch (err) {
      setError('Error updating status');
      console.error(err);
    }
  };

  const handleSave = async (formData: any) => {
    if (!registration) return;

    try {
      // First update the registration data
      const response = await fetch(`/api/admin/registrations/${registration.id}`, {
        method: 'PATCH',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(formData),
      });

      if (!response.ok) {
        throw new Error('Failed to update registration');
      }

      const updatedRegistration = await response.json();

      // If there's a file, upload it separately
      if (formData.file) {
        const fileFormData = new FormData();
        fileFormData.append('file', formData.file);
        fileFormData.append('registrationId', registration.id);

        const fileResponse = await fetch('/api/upload', {
          method: 'POST',
          body: fileFormData,
        });

        if (!fileResponse.ok) {
          throw new Error('Failed to upload file');
        }
      }

      setRegistration(updatedRegistration);
      setIsEditing(false);
    } catch (err) {
      setError('Error updating registration');
      console.error(err);
    }
  };

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

  if (!session || !['ADMIN', 'SUPERADMIN'].includes(session.user.role)) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <h1 className="text-2xl font-bold text-red-600 mb-4">Access Denied</h1>
          <p className="text-gray-600">You don't have permission to view this page.</p>
        </div>
      </div>
    );
  }

  if (loading) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
          <p className="mt-4 text-gray-600">Loading application...</p>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <h1 className="text-2xl font-bold text-red-600 mb-4">Error</h1>
          <p className="text-gray-600">{error}</p>
          <button 
            onClick={() => router.push('/admin')}
            className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
          >
            Back to Admin
          </button>
        </div>
      </div>
    );
  }

  if (!registration) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <h1 className="text-2xl font-bold text-red-600 mb-4">Application Not Found</h1>
          <p className="text-gray-600">The application you're looking for doesn't exist.</p>
          <button 
            onClick={() => router.push('/admin')}
            className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
          >
            Back to Admin
          </button>
        </div>
      </div>
    );
  }

  return (
    <LayoutWithSidebar>
      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
        <div className="mb-8 flex justify-between items-center">
          <div className="flex items-center space-x-4">
            <button
              onClick={() => router.push('/admin')}
              className="flex items-center text-gray-600 hover:text-gray-900"
            >
              <svg
                className="w-6 h-6 mr-2"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M10 19l-7-7m0 0l7-7m-7 7h18"
                />
              </svg>
              {isFrench ? 'Retour' : 'Back'}
            </button>
            <h1 className="text-2xl font-bold text-gray-900">
              {isFrench ? 'Détails de la demande' : 'Application Details'}
        </h1>
          </div>
          <div className="flex space-x-4">
            <select
              value={registration.status}
              onChange={(e) => handleStatusChange(e.target.value as 'PENDING' | 'APPROVED' | 'REJECTED')}
              className={`px-4 py-2 rounded-md ${
            registration.status === 'APPROVED' ? 'bg-green-100 text-green-800' :
            registration.status === 'REJECTED' ? 'bg-red-100 text-red-800' :
            'bg-yellow-100 text-yellow-800'
              }`}
            >
              <option value="PENDING">{isFrench ? 'En attente' : 'Pending'}</option>
              <option value="APPROVED">{isFrench ? 'Approuvé' : 'Approved'}</option>
              <option value="REJECTED">{isFrench ? 'Rejeté' : 'Rejected'}</option>
            </select>
            <button
              onClick={() => setIsEditing(!isEditing)}
              className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
            >
              {isEditing 
                ? (isFrench ? 'Annuler' : 'Cancel')
                : (isFrench ? 'Modifier' : 'Edit')
              }
            </button>
        </div>
        </div>

        {error && (
          <div className="mb-4 p-4 bg-red-50 border border-red-200 rounded-md text-red-600">
            {error}
          </div>
        )}

        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.5 }}
        >
          <RegistrationForm
            isFrench={isFrench}
            initialLocale={registration.preferredLanguage}
            initialData={registration}
            isEditing={isEditing}
            onSave={handleSave}
            isAdmin={true}
          />
        </motion.div>

        <div className="mt-4">
          <div className="mb-2"><b>Facility:</b> {registration.detaineeInfo?.facility ? getFacilityName(registration.detaineeInfo.facility) : '-'}</div>
        </div>
      </div>
    </LayoutWithSidebar>
  );
} 

CasperSecurity Mini