![]() 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/hire/ |
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';
import Head from 'next/head';
import LayoutWithSidebar from '../../components/LayoutWithSidebar';
import { motion } from 'framer-motion';
import {
MessageSquare, Calendar, Clock, DollarSign,
ArrowLeft, ArrowRight, User, FileText
} from 'lucide-react';
import toast from 'react-hot-toast';
interface Lawyer {
id: string;
name: string;
hourlyRate?: number;
specialization?: string;
isVerified: boolean;
}
const ConsultationPage: React.FC = () => {
const router = useRouter();
const { data: session } = useSession();
const [lawyer, setLawyer] = useState<Lawyer | null>(null);
const [loading, setLoading] = useState(true);
const [submitting, setSubmitting] = useState(false);
const [formData, setFormData] = useState({
preferredDate: '',
preferredTime: '',
duration: '60',
consultationType: 'GENERAL',
message: ''
});
const { lawyerId } = router.query;
useEffect(() => {
if (lawyerId) {
fetchLawyerDetails();
}
}, [lawyerId]);
const fetchLawyerDetails = async () => {
try {
const response = await fetch(`/api/user/${lawyerId}`);
if (response.ok) {
const data = await response.json();
setLawyer(data.user);
}
} catch (error) {
console.error('Error fetching lawyer details:', error);
toast.error('Failed to load lawyer details');
} finally {
setLoading(false);
}
};
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!formData.preferredDate || !formData.preferredTime) {
toast.error('Please select a date and time');
return;
}
setSubmitting(true);
try {
const response = await fetch('/api/hire/consultation', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
lawyerId,
...formData
}),
});
if (response.ok) {
toast.success('Consultation request sent successfully!');
router.push('/user/dashboard');
} else {
const error = await response.json();
toast.error(error.error || 'Failed to send request');
}
} catch (error) {
console.error('Error sending consultation request:', error);
toast.error('Failed to send request');
} finally {
setSubmitting(false);
}
};
const consultationTypes = [
{ value: 'GENERAL', label: 'General Legal Advice' },
{ value: 'CASE_REVIEW', label: 'Case Review' },
{ value: 'DOCUMENT_REVIEW', label: 'Document Review' },
{ value: 'CONTRACT_REVIEW', label: 'Contract Review' },
{ value: 'LITIGATION_STRATEGY', label: 'Litigation Strategy' },
{ value: 'SETTLEMENT_NEGOTIATION', label: 'Settlement Negotiation' }
];
const timeSlots = [
'09:00', '09:30', '10:00', '10:30', '11:00', '11:30',
'13:00', '13:30', '14:00', '14:30', '15:00', '15:30',
'16:00', '16:30', '17:00', '17:30'
];
if (loading) {
return (
<LayoutWithSidebar>
<div className="flex items-center justify-center min-h-screen">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
</div>
</LayoutWithSidebar>
);
}
if (!lawyer) {
return (
<LayoutWithSidebar>
<div className="text-center py-12">
<h1 className="text-2xl font-bold text-gray-900 mb-4">Lawyer not found</h1>
<button
onClick={() => router.back()}
className="text-blue-600 hover:text-blue-800"
>
Go back
</button>
</div>
</LayoutWithSidebar>
);
}
return (
<LayoutWithSidebar>
<Head>
<title>Book Consultation - {lawyer.name}</title>
</Head>
<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">
<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">Book Consultation</h1>
<p className="text-gray-600">Schedule a consultation with {lawyer.name}</p>
</div>
</div>
</motion.div>
{/* Lawyer Info */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 }}
className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6"
>
<div className="flex items-center gap-4">
<div className="w-16 h-16 bg-gradient-to-br from-blue-400 to-purple-500 rounded-full flex items-center justify-center">
<User className="h-8 w-8 text-white" />
</div>
<div>
<h2 className="text-xl font-semibold text-gray-900 flex items-center">
{lawyer.name}
{lawyer.isVerified && (
<span className="ml-2 text-blue-600">✓ Verified</span>
)}
</h2>
{lawyer.specialization && (
<p className="text-gray-600">{lawyer.specialization}</p>
)}
{lawyer.hourlyRate && (
<p className="text-green-600 font-medium">${lawyer.hourlyRate}/hour</p>
)}
</div>
</div>
</motion.div>
{/* Consultation 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">
<MessageSquare className="h-5 w-5 mr-2 text-blue-600" />
Consultation Details
</h2>
<div className="space-y-6">
{/* Consultation Type */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Consultation Type
</label>
<select
name="consultationType"
value={formData.consultationType}
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"
>
{consultationTypes.map(type => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
</div>
{/* Date and Time */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Preferred Date
</label>
<input
type="date"
name="preferredDate"
value={formData.preferredDate}
onChange={handleInputChange}
min={new Date().toISOString().split('T')[0]}
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>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Preferred Time
</label>
<select
name="preferredTime"
value={formData.preferredTime}
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"
required
>
<option value="">Select time</option>
{timeSlots.map(time => (
<option key={time} value={time}>
{time}
</option>
))}
</select>
</div>
</div>
{/* Duration */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Duration
</label>
<select
name="duration"
value={formData.duration}
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"
>
<option value="30">30 minutes</option>
<option value="60">1 hour</option>
<option value="90">1.5 hours</option>
<option value="120">2 hours</option>
</select>
</div>
{/* Message */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Additional Details
</label>
<textarea
name="message"
value={formData.message}
onChange={handleInputChange}
rows={4}
placeholder="Describe your legal issue or what you'd like to discuss..."
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
{/* Cost Estimate */}
{lawyer.hourlyRate && (
<div className="bg-blue-50 border border-blue-200 rounded-md p-4">
<div className="flex items-center justify-between">
<div>
<h3 className="font-medium text-blue-900">Estimated Cost</h3>
<p className="text-sm text-blue-700">
{lawyer.hourlyRate} × {parseInt(formData.duration) / 60} hours
</p>
</div>
<div className="text-right">
<div className="text-lg font-bold text-blue-900">
${((lawyer.hourlyRate * parseInt(formData.duration)) / 60).toFixed(2)}
</div>
<div className="text-sm text-blue-700">CAD</div>
</div>
</div>
</div>
)}
</div>
{/* Submit Button */}
<div className="mt-8 flex justify-end">
<button
type="submit"
disabled={submitting}
className={`px-6 py-3 rounded-lg transition-colors ${
submitting
? 'bg-gray-400 cursor-not-allowed'
: 'bg-blue-600 text-white hover:bg-blue-700'
}`}
>
{submitting ? (
<div className="flex items-center">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
Sending Request...
</div>
) : (
<div className="flex items-center">
Book Consultation
<ArrowRight className="h-4 w-4 ml-2" />
</div>
)}
</button>
</div>
</motion.form>
</div>
</LayoutWithSidebar>
);
};
export default ConsultationPage;