url = $url; } public function registerPatient(Request $request) { $validatedData = $request->validate([ 'first_name' => 'required|string|max:255', 'last_name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:patients', 'password' => 'required', // 'state' => 'required', 'dob' => 'required|date_format:Y-m-d', // 'address' => 'required', // 'country' => 'required', 'phone_no' => 'required' ]); $defaultPassword = $validatedData['password']; $patient = Patient::create([ 'first_name' => $validatedData['first_name'], 'last_name' => $validatedData['last_name'], 'phone_no' => $validatedData['phone_no'], 'email' => $validatedData['email'], 'password' => Hash::make($defaultPassword), // 'city' => $validatedData['city'], // 'state' => $validatedData['state'], 'dob' => $validatedData['dob'], // 'zip_code' => $request->input('zip_code') ?? "", // 'shipping_address' => $request->input('shipping_address') ?? "", // 'shipping_city' => $request->input('shipping_city') ?? "", // 'shipping_state' => $request->input('shipping_state') ?? "", // 'shipping_country' => $request->input('shipping_country') ?? "", // 'shipping_zipcode' => $request->input('shipping_zipcode') ?? "", // 'address' => $validatedData['address'], // 'lat' => $request->get('lat'), // 'long' => $request->get('long'), // 'country' => $validatedData['country'], 'gender' => $request->input('gender') ?? "", // 'marital_status' => $request->input('marital_status') ?? "", // 'height' => $request->input('height') ?? "", // 'weight' => $request->input('weight') ?? "", ]); $token = $patient->createToken('auth_token')->plainTextToken; if ($patient->dob) { $birthDate = new DateTime($patient->dob); $today = new DateTime(date('Y-m-d')); $age = $today->diff($birthDate)->y; $patient->age = $age; } else { $patient->age = 0; } PatientRegActivity::create([ 'patient_id' => $patient->id, 'activity' => 'patient_registered' ]); $setting = Setting::find(1); event(new PatientRegistered($patient, $validatedData)); return response() ->json([ 'data' => $patient, 'access_token' => $token, 'token_type' => 'Bearer', 'password' => $defaultPassword ]); } //write for public function forgotPassword(Request $request) { $request->validate([ 'email' => 'required|email', ]); $patient = Patient::where('email', $request->email)->first(); if (!$patient) { return response()->json(['message' => 'Email does not exist'], 404); } $token = Str::random(60); $patient->update(['remember_token' => $token]); // Send reset link email Mail::send('emails.password_reset', ['token' => $token], function ($message) use ($request) { $message->to($request->email); $message->subject('Password Reset Request'); }); return response()->json(['message' => 'Password reset link sent']); } public function resetPassword(Request $request) { $request->validate([ 'token' => 'required', 'password' => 'required|confirmed', ]); $patient = Patient::where('remember_token', $request->token)->first(); if (!$patient) { return response()->json(['message' => 'Invalid token'], 400); } $patient->update([ 'password' => Hash::make($request->password), 'remember_token' => null, ]); return response()->json(['message' => 'Password reset successful']); } public function updatePatient(Request $request) { $patient = Auth::guard('patient')->user(); // Collect only the fields that are present in the request $dataToUpdate = array_filter($request->only([ 'first_name', 'last_name', 'email', 'phone_no', 'city', 'state', 'address', 'zip_code', 'country', 'dob', 'gender', 'marital_status', 'height', 'weight' ]), function ($value) { return $value !== null; }); // Update the patient with the collected data $patient->update($dataToUpdate); return response()->json([ 'data' => $patient, 'message' => 'Patient updated successfully' ]); } public function editPatient($id, Request $request) { $patient = Patient::where('id', $id)->first(); if (!empty($request->input('address'))) $patient->address = $request->input('address'); if (!empty($request->input('city'))) $patient->city = $request->input('city'); if (!empty($request->input('state'))) $patient->state = $request->input('state'); if (!empty($request->input('zip_code'))) $patient->zip_code = $request->input('zip_code'); if (!empty($request->input('country'))) $patient->country = $request->input('country'); if (!empty($request->input('dob'))) $patient->dob = $request->input('dob'); if (!empty($request->input('gender'))) $patient->gender = $request->input('gender'); if (!empty($request->input('marital_status'))) $patient->marital_status = $request->input('marital_status'); if (!empty($request->input('height'))) $patient->height = $request->input('height'); if (!empty($request->input('weight'))) $patient->weight = $request->input('weight'); $patient->save(); $patient->save(); return response()->json([ 'data' => $patient, 'message' => 'Patient updated successfully' ]); } // PatientController public function loginPatient(Request $request) { $validatedData = $request->validate([ 'email' => 'required|email', 'password' => 'required' ]); $patient = Patient::where('email', $validatedData['email'])->firstOrFail(); if ($patient->dob) { $birthDate = new DateTime($patient->dob); $today = new DateTime(date('Y-m-d')); $age = $today->diff($birthDate)->y; $patient->age = $age; } else { $patient->age = 0; } if (!$patient || !Hash::check($validatedData['password'], $patient->password)) { return response([ 'message' => 'Invalid credentials' ], 401); } $token = $patient->createToken('auth_token')->plainTextToken; return response()->json([ 'data' => $patient, 'access_token' => $token, 'token_type' => 'Bearer', ]); } public function updatePassword(Request $request) { $request->validate([ /* 'old_password' => 'required', */ 'new_password' => 'required|string|min:8', ]); $patient = Auth::guard('patient')->user(); // Check if the old password is correct /* if (!Hash::check($request->old_password, $patient->password)) { return response([ 'message' => 'The provided old password is incorrect.' ], 400); // Use 400 for bad request } */ // Update the password $patient->password = Hash::make($request->new_password); $patient->save(); return response()->json([ 'message' => 'Password updated successfully.' ]); } // Inside your AppointmentController class: public function availableSlots($date) { // Ensure date is in a valid format $date = Carbon::parse($date); $originalDate = Carbon::parse($date); // Generate all possible 30-minute slots between 9 AM and 4 PM $slots = collect(); $startTime = Carbon::parse($date)->subHours(24)->setTime(9, 0, 0); $endTime = Carbon::parse($date)->addHours(24)->setTime(16, 0, 0); while ($startTime < $endTime) { $slots->push($startTime->format('Y-m-d H:i:s')); $startTime->addMinutes(15); } $user = Auth::guard('patient')->user(); // Filter out booked slots $bookedAppointments = Appointment::where("patient_id", $user->id) ->where('appointment_date', '>=', $date->format('Y-m-d')) ->where('appointment_date', '<', $date->addDay()->format('Y-m-d')) ->pluck('appointment_date'); $availableSlots = $slots->diff($bookedAppointments); $formattedSlots = $availableSlots->map(function ($slot) { $start = Carbon::parse($slot); $startTime = $start->format('Y-m-d H:i:s'); return $startTime; }); // Additional checking if slot is booked $formattedSlots = $formattedSlots->filter(function ($slot) use ($originalDate) { $time = Carbon::parse($slot); return !Appointment::where('appointment_time', $time->format('H:i:s')) ->where('appointment_date', $originalDate->format('Y-m-d')) ->exists(); }); return response()->json([ 'available_slots' => $formattedSlots->toArray() ]); } public function bookAppointment(Request $request) { $validatedData = $request->validate([ /* 'telemed_pros_id' => 'required|exists:telemed_pros,id', */ 'patient_id' => 'required|exists:patients,id', 'appointment_time' => 'required|date_format:H:i:s', 'appointment_date' => 'required|date_format:Y-m-d', 'patient_name' => 'required', 'patient_email' => 'required', 'timezone' => 'required', ]); try { $tz = new DateTimeZone($validatedData['timezone']); $standardTz = $tz->getName(); } catch (Exception $e) { return response()->json([ 'message' => $e->getMessage() ], 400); } try { $timezoneMap = [ 'EST' => 'America/New_York', 'EDT' => 'America/New_York', 'CST' => 'America/Chicago', 'CDT' => 'America/Chicago', 'MST' => 'America/Denver', 'MDT' => 'America/Denver', 'PST' => 'America/Los_Angeles', 'PDT' => 'America/Los_Angeles', // Add more mappings as needed ]; $timezone = $validatedData['timezone']; if (array_key_exists($timezone, $timezoneMap)) { $timezone = $timezoneMap[$timezone]; } $appointmentDateTime = new DateTime( $validatedData['appointment_date'] . ' ' . $validatedData['appointment_time'], new DateTimeZone($timezone) ); $appointmentDateTime->setTimezone(new DateTimeZone('UTC')); $validatedData['appointment_time'] = $appointmentDateTime->format('H:i:s'); $validatedData['appointment_date'] = $appointmentDateTime->format('Y-m-d'); } catch (Exception $e) { return response()->json([ 'message' => $e->getMessage() ], 400); } $availableTelemedPros = Telemedpro::select("telemed_pros.id", "telemed_pros.name")/* ->where('is_busy', false) */ ->leftJoin('appointments', function ($join) use ($validatedData) { $join->on('telemed_pros.id', '=', 'appointments.telemed_pros_id') ->where('appointments.appointment_time', '=', $validatedData['appointment_time']) ->where('appointments.appointment_date', '=', $validatedData['appointment_date']); }) ->whereNull('appointments.id') ->first(); if (!$availableTelemedPros) return response()->json([ 'message' => 'Appointment time not available' ], 400); $existingAppointment = Appointment::where('telemed_pros_id', $availableTelemedPros->id) ->where('appointment_time', $validatedData['appointment_time']) ->where('appointment_date', $validatedData['appointment_date']) ->first(); if ($existingAppointment) { return response()->json([ 'message' => 'Appointment time not available' ], 400); } $validatedData['telemed_pros_id'] = $availableTelemedPros->id; $validatedData['status'] = 'pending'; // Create the appointment $appointment = Appointment::create($validatedData); //$appointment_booking_tokens = $this->bookAppointmentApi($appointment, $availableTelemedPros); $appointment_booking_tokens = "null"; /* $appointment->agent_call_token = $appointment_booking_tokens['tokenAgent']; $appointment->patient_call_token = $appointment_booking_tokens['tokenPatient']; */ $appointment->agent_call_token = "null"; $appointment->patient_call_token = "null"; $appointment->save(); PatientRegActivity::create([ 'patient_id' => $validatedData['patient_id'], 'activity' => 'patient_appointment_booked' ]); $patient = $appointment->patient; $datetimeUtc = $appointment->appointment_date . ' ' . $appointment->appointment_time; $dateTimeUtc = Carbon::createFromFormat('Y-m-d H:i:s', $datetimeUtc, 'UTC'); $appointmentTimeZone = new CarbonTimeZone($appointment->timezone); $dateTimeInAppointmentTimeZone = $dateTimeUtc->setTimezone($appointmentTimeZone); $appointment->appointment_date = $appointmentDate = $dateTimeInAppointmentTimeZone->format('Y-m-d'); $appointment->appointment_time = $appointmentTime = $dateTimeInAppointmentTimeZone->format('H:i:s'); $setting = Setting::find(1); event(new AppointmentBooked($appointment)); $cart = Cart::find($request->input("cart_id")); $cart->appointment_id = $appointment->id; $cart->save(); return response()->json([ 'message' => 'Appointment booked successfully', 'meeting_id' => $appointment->agent_call_token, 'appointment' => $appointment, 'appointment_time' => $validatedData['appointment_time'], 'appointment_date' => $validatedData['appointment_date'] ]); } public function appointmentDetail(Appointment $appointment) { $patient = Patient::find($appointment->patient_id); $telemedPro = Telemedpro::find($appointment->telemed_pros_id); $doctor_appointment = DoctorAppointment::select('doctor_appointments.*', 'doctors.name as name')->where('appointment_id', $appointment->id) ->leftjoin('doctors', 'doctors.id', '=', 'doctor_appointments.doctor_id') ->first(); if (!$doctor_appointment) $doctor_appointment = []; else $doctor_appointment = $doctor_appointment->toArray(); return response()->json([ 'patient' => $patient->toArray() ?? [], 'telemedPro' => $telemedPro->toArray() ?? [], 'doctor_appointment' => $doctor_appointment, 'video_url' => "https://plugnmeet.codelfi.com/recordings/" . $appointment->video_token . ".mp4", ]); } public function bookAppointmentApi($appointment, $availableTelemedPros) { $roomName = 'appointment-' . $appointment->id . "-" . uniqid(); $opts = (new RoomCreateOptions()) ->setName($roomName) ->setEmptyTimeout(10) ->setMaxParticipants(5); $host = "https://plugnmeet.codelfi.com"; $svc = new RoomServiceClient($host, config('app.LK_API_KEY'), config('app.LK_API_SECRET')); $room = $svc->createRoom($opts); $participantPatientName = "patient-" . uniqid() . $appointment->patient->first_name . " " . $appointment->patient->last_name; $tokenOptionsPatient = (new AccessTokenOptions()) ->setIdentity($participantPatientName); $videoGrantPatient = (new VideoGrant()) ->setRoomJoin() ->setRoomName($roomName); $tokenPatient = (new AccessToken(config('app.LK_API_KEY'), config('app.LK_API_SECRET'))) ->init($tokenOptionsPatient) ->setGrant($videoGrantPatient) ->toJwt(); $participantAgentName = "agent-" . uniqid() . $availableTelemedPros->name; $tokenOptionsAgent = (new AccessTokenOptions()) ->setIdentity($participantAgentName); $videoGrantAgent = (new VideoGrant()) ->setRoomJoin() ->setRoomName($roomName); $tokenAgent = (new AccessToken(config('app.LK_API_KEY'), config('app.LK_API_SECRET'))) ->init($tokenOptionsAgent) ->setGrant($videoGrantAgent) ->toJwt(); return [ 'tokenPatient' => $tokenPatient, 'tokenAgent' => $tokenAgent, ]; } public function addPatientToQueue($patientId) { // Try to get existing queue $queue = Queue::where('patient_id', $patientId)->first(); // No existing queue if (!$queue) { // Create new queue entry $queue = new Queue; $queue->patient_id = $patientId; $queue->queue_number = Queue::max('queue_number') + 1; $queue->save(); return response()->json([ 'message' => 'Added to queue', 'queue_number' => $queue->queue_number ]); } else { if ($queue->queue_number == 0) { $appointment = Appointment::create([ 'patient_id' => $patientId, 'appointment_date' => Carbon::now()->format('Y-m-d'), 'appointment_time' => Carbon::now()->format('H:i:s'), ]); return response()->json([ 'message' => 'ok', 'meeting_id' => $appointment->meeting_id, 'queue_number' => 0 ]); } else { return response()->json([ 'message' => 'Waiting in queue', 'queue_number' => $queue->queue_number ]); } } } public function getAppointmentsByPatientId(int $patientId) { try { $appointments = Appointment::where('patient_id', $patientId) ->with('telemedPro') // Eager load the associated telemed pro /* ->orderBy('appointment_time', 'desc') */ // Optional: sort by appointment time ->get(); return response()->json($appointments, 200); } catch (\Exception $e) { return response()->json(['error' => 'Failed to retrieve appointments'], 500); } } public function getDoctorAppointmentsByPatientId(int $patientId) { try { $appointments = DoctorAppointment::select("patients.first_name", "patients.last_name", "doctor_appointments.*") // Eager load the associated telemed pro ->leftJoin("patients", "patients.id", "doctor_appointments.patient_id") ->where('patient_id', $patientId) /* ->orderBy('appointment_time', 'desc') */ // Optional: sort by appointment time ->get(); return response()->json($appointments, 200); } catch (\Exception $e) { return response()->json(['error' => 'Failed to retrieve appointments'], 500); } } public function getLabcorpData(Request $request) { $url = 'https://www.labcorp.com/labs-and-appointments/results'; $params = [ 'geo_address' => $request->input('address'), 'address_single' => $request->input('address'), 'city' => $request->input('city'), 'state' => $request->input('state'), 'zip' => $request->input('zip'), 'service' => 'ROUTINE_PHLEBOTOMY', 'radius' => 25, 'gps' => false, ]; $response = Http::get($url, $params); // Check if the request was successful (status code 200) if ($response->successful()) { // Extract JSON using regular expressions $pattern = '/