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

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/private_html/src/components/NewCaseForm.tsx
import React, { useState } from 'react';
import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';
import { motion } from 'framer-motion';
import { FileText, ArrowLeft, AlertCircle } from 'lucide-react';
import toast from 'react-hot-toast';
import Image from 'next/image';

interface NewCaseFormProps {
  modalMode?: boolean;
}

const NewCaseForm: React.FC<NewCaseFormProps> = ({ modalMode }) => {
  const router = useRouter();
  const { data: session, status } = useSession();
  const [submitting, setSubmitting] = useState(false);
  const [formData, setFormData] = useState({
    title: '',
    caseType: 'CIVIL',
    priority: 'MEDIUM',
    budget: '',
    description: '',
    assignedTo: '',
    isPublic: false
  });
  const [logoUrl, setLogoUrl] = useState<string | null>(null);
  const [logoFile, setLogoFile] = useState<File | null>(null);

  // Redirect if not authenticated
  React.useEffect(() => {
    if (status === 'loading') return; // Still loading
    if (!session) {
      router.push('/auth/login');
    }
  }, [session, status, router]);

  // Show loading state while session is loading
  if (status === 'loading') {
    return (
      <div className="max-w-2xl mx-auto px-4 py-8">
        <div className="text-center">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
          <p className="mt-2 text-gray-600">Loading...</p>
        </div>
      </div>
    );
  }

  // Don't render form if not authenticated
  if (!session) {
    return null;
  }

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
    const { name, value, type } = e.target;
    const checked = type === 'checkbox' ? (e.target as HTMLInputElement).checked : undefined;
    setFormData(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  };

  const handleLogoChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      setLogoFile(file);
      setLogoUrl(URL.createObjectURL(file));
    }
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!formData.title || !formData.description || !logoFile) {
      toast.error('Please fill in all required fields and upload a logo');
      return;
    }
    setSubmitting(true);
    try {
      // Upload logo first
      let uploadedLogoUrl = '';
      if (logoFile) {
        const formDataLogo = new FormData();
        formDataLogo.append('file', logoFile);
        const uploadRes = await fetch('/api/upload', {
          method: 'POST',
          body: formDataLogo
        });
        if (!uploadRes.ok) {
          const errorData = await uploadRes.json().catch(() => ({ error: 'Unknown error' }));
          console.error('Upload failed:', uploadRes.status, errorData);
          throw new Error(`Failed to upload logo: ${errorData.error || uploadRes.statusText}`);
        }
        const uploadData = await uploadRes.json();
        uploadedLogoUrl = uploadData.url;
      }
      const response = await fetch('/api/cases', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          ...formData,
          logoUrl: uploadedLogoUrl,
          status: 'PENDING',
          budget: formData.budget ? parseFloat(formData.budget) : null,
          assignedTo: formData.assignedTo || null,
          isPublic: formData.isPublic
        }),
      });
      if (response.ok) {
        toast.success('Case created successfully!');
        if (session?.user?.role === 'CLIENT') {
          router.push('/client/dashboard');
        } else if (session?.user?.role === 'LAWYER') {
          router.push('/lawyer/dashboard');
        } else if (session?.user?.role === 'ADMIN' || session?.user?.role === 'SUPERADMIN') {
          router.push('/admin/cases');
        } else {
          router.push('/admin/cases');
        }
      } else {
        const error = await response.json();
        toast.error(error.error || 'Failed to create case');
      }
    } catch (error) {
      console.error('Error creating case:', error);
      toast.error(error instanceof Error ? error.message : 'Failed to create case');
    } finally {
      setSubmitting(false);
    }
  };

  const caseTypes = [
    { value: 'CIVIL', label: 'Civil Litigation' },
    { value: 'CRIMINAL', label: 'Criminal Defense' },
    { value: 'FAMILY', label: 'Family Law' },
    { value: 'CORPORATE', label: 'Corporate Law' },
    { value: 'REAL_ESTATE', label: 'Real Estate' },
    { value: 'INTELLECTUAL_PROPERTY', label: 'Intellectual Property' },
    { value: 'EMPLOYMENT', label: 'Employment Law' },
    { value: 'IMMIGRATION', label: 'Immigration' },
    { value: 'MEDIATION', label: 'Mediation' },
    { value: 'INVESTIGATION', label: 'Investigation' },
    { value: 'EXPERT_TESTIMONY', label: 'Expert Testimony' },
    { value: 'NOTARIAL', label: 'Notarial Services' },
    { value: 'OTHER', label: 'Other' }
  ];

  const priorities = [
    { value: 'LOW', label: 'Low Priority' },
    { value: 'MEDIUM', label: 'Medium Priority' },
    { value: 'HIGH', label: 'High Priority' },
    { value: 'URGENT', label: 'Urgent' }
  ];

  const isAdmin = session?.user?.role === 'ADMIN' || session?.user?.role === 'SUPERADMIN';
  const isLawyer = session?.user?.role === 'LAWYER';
  const isClient = session?.user?.role === 'CLIENT';

  return (
    <div className="max-w-2xl mx-auto px-4 py-8">
      {/* Header */}
      <motion.div
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        className="mb-8"
      >
        <div className="flex items-center gap-4 mb-4">
          {!modalMode && (
            <button
              onClick={() => router.back()}
              className="p-2 text-gray-600 hover:text-gray-800 transition-colors"
            >
              <ArrowLeft className="h-5 w-5" />
            </button>
          )}
          <div>
            <h1 className="text-3xl font-bold text-gray-900">Create New Case</h1>
            <p className="text-gray-600">
              {isAdmin ? 'Create a new case in the system' :
                isLawyer ? 'Create a case for client representation' :
                'Create a case to hire a lawyer for representation'}
            </p>
          </div>
        </div>
      </motion.div>
      {/* Info Alert */}
      <motion.div
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: 0.1 }}
        className="bg-blue-50 border border-blue-200 rounded-md p-4 mb-6"
      >
        <div className="flex items-start">
          <AlertCircle className="h-5 w-5 text-blue-400 mr-2 mt-0.5" />
          <div className="text-sm text-blue-800">
            <strong>Universal Case System</strong>
            <br />
            This case will be integrated into the unified case management system accessible by all authorized roles.
            {isClient && ' Creating a case helps lawyers understand your legal needs and provide better representation.'}
            {isLawyer && ' You can assign this case to team members or handle it yourself.'}
            {isAdmin && ' You can assign this case to any lawyer or keep it unassigned for review.'}
          </div>
        </div>
      </motion.div>
      {/* Case Form */}
      <motion.form
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: 0.2 }}
        onSubmit={handleSubmit}
        className="bg-white rounded-lg shadow-sm border border-gray-200 p-6"
      >
        <h2 className="text-xl font-semibold text-gray-900 mb-6 flex items-center">
          <FileText className="h-5 w-5 mr-2 text-blue-600" />
          Case Information
        </h2>
        <div className="space-y-6">
          {/* Logo Uploader */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Case Logo *
            </label>
            <div
              className="w-full flex flex-col items-center justify-center border-2 border-dashed border-blue-400 rounded-md p-4 cursor-pointer bg-blue-50 hover:bg-blue-100"
              onClick={() => document.getElementById('case-logo-input')?.click()}
              style={{ minHeight: 120 }}
            >
              {logoUrl ? (
                <Image src={logoUrl} alt="Case Logo Preview" width={96} height={96} className="rounded shadow mb-2" />
              ) : (
                <span className="text-blue-400">Drag & drop or click to upload a logo</span>
              )}
              <input
                id="case-logo-input"
                type="file"
                accept="image/*"
                className="hidden"
                onChange={handleLogoChange}
              />
            </div>
            {logoUrl && (
              <div className="text-xs text-gray-500 mt-1">Logo preview shown above</div>
            )}
          </div>
          {/* Case Title */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Case Title *
            </label>
            <input
              type="text"
              name="title"
              value={formData.title}
              onChange={handleInputChange}
              placeholder="Brief description of your case"
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              required
            />
          </div>
          {/* Case Type */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Case Type
            </label>
            <select
              name="caseType"
              value={formData.caseType}
              onChange={handleInputChange}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            >
              {caseTypes.map(type => (
                <option key={type.value} value={type.value}>{type.label}</option>
              ))}
            </select>
          </div>
          {/* Priority */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Priority
            </label>
            <select
              name="priority"
              value={formData.priority}
              onChange={handleInputChange}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            >
              {priorities.map(priority => (
                <option key={priority.value} value={priority.value}>{priority.label}</option>
              ))}
            </select>
          </div>
          {/* Budget */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Budget (optional)
            </label>
            <input
              type="number"
              name="budget"
              value={formData.budget}
              onChange={handleInputChange}
              placeholder="Proposed budget for the case"
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              min="0"
            />
          </div>
          {/* Description */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Description *
            </label>
            <textarea
              name="description"
              value={formData.description}
              onChange={handleInputChange}
              placeholder="Describe your case in detail"
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              rows={4}
              required
            />
          </div>
          {/* Assign To (for admin/lawyer) */}
          {(isAdmin || isLawyer) && (
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Assign To (Lawyer ID, optional)
              </label>
              <input
                type="text"
                name="assignedTo"
                value={formData.assignedTo}
                onChange={handleInputChange}
                placeholder="Lawyer ID to assign this case"
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>
          )}
          {/* Public Case Checkbox */}
          <div className="flex items-center">
            <input
              type="checkbox"
              name="isPublic"
              checked={!!formData.isPublic}
              onChange={handleInputChange}
              className="h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
            />
            <label className="ml-2 block text-sm text-gray-700">
              Make this case public (visible to all lawyers)
            </label>
          </div>
        </div>
        <div className="mt-8 flex justify-end">
          <button
            type="submit"
            className="bg-blue-600 text-white px-6 py-2 rounded-lg font-semibold hover:bg-blue-700 transition-colors disabled:opacity-50"
            disabled={submitting}
          >
            {submitting ? 'Submitting...' : 'Create Case'}
          </button>
        </div>
      </motion.form>
    </div>
  );
};

export default NewCaseForm; 

CasperSecurity Mini