424 lines
15 KiB
PHP
424 lines
15 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Agent;
|
|
|
|
use Agence104\LiveKit\AccessToken;
|
|
use Agence104\LiveKit\AccessTokenOptions;
|
|
use Agence104\LiveKit\EgressServiceClient;
|
|
use Agence104\LiveKit\RoomCreateOptions;
|
|
use Agence104\LiveKit\RoomServiceClient;
|
|
use Agence104\LiveKit\VideoGrant;
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use App\Classes\JassJWT;
|
|
use App\Events\AppointmentCallEnded;
|
|
use App\Events\AppointmentCreated;
|
|
use App\Events\DeviceCurrentStatus;
|
|
use App\Models\Appointment;
|
|
use App\Models\Doctor;
|
|
use App\Models\DoctorAppointment;
|
|
use App\Models\Lab;
|
|
use App\Models\Patient;
|
|
use App\Models\PatientNote;
|
|
use App\Models\Telemedpro;
|
|
use Carbon\Carbon;
|
|
use DateTime;
|
|
use Error;
|
|
use Exception;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Livekit\EncodedFileOutput;
|
|
use Livekit\EncodedFileType;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
class MeetingController extends Controller
|
|
{
|
|
public function getAsseblyAiToekn()
|
|
{
|
|
$response = Http::withHeaders([
|
|
'Authorization' => '0014470a9fa14b598a73cc0133acca8c',
|
|
])->post('https://api.assemblyai.com/v2/realtime/token', [
|
|
'expires_in' => 1600
|
|
]);
|
|
|
|
return $response->body();
|
|
}
|
|
public function show($meeting_id)
|
|
{
|
|
return view('agent.jetsi', compact('meeting_id'));
|
|
}
|
|
public function joinMeeting($meeting_id)
|
|
{
|
|
$jassToken = JassJWT::generate();
|
|
$appoinement = Appointment::where("meeting_id", $meeting_id)->firstOrFail();
|
|
|
|
return view('agent.join-meeting', compact('meeting_id'), compact('jassToken'));
|
|
}
|
|
public function startCall($patient_id, $agent_id, $appointment_id, Request $request)
|
|
{
|
|
$call_type = $request->input('call_type');
|
|
$telemed_pro = Telemedpro::where("id", $agent_id)->firstOrFail();
|
|
$appointment = Appointment::find($appointment_id);
|
|
$appointment->in_call = 1;
|
|
$appointment->start_time = Carbon::now()->format('Y-m-d H:i:s');
|
|
$appointment_booking_tokens = $this->bookAppointmentApi($appointment, $telemed_pro);
|
|
$appointment->agent_call_token = $appointment_booking_tokens['tokenAgent'];
|
|
$appointment->patient_call_token = $appointment_booking_tokens['tokenPatient'];
|
|
$appointment->telemed_pros_id = $agent_id;
|
|
$appointment->save();
|
|
|
|
event(new AppointmentCreated($patient_id, $appointment->id, $appointment->patient_call_token, $call_type));
|
|
|
|
return response()->json([
|
|
'message' => 'Appointment created!',
|
|
'appointment_id' => $appointment->id,
|
|
'meeting_id' => $appointment->agent_call_token,
|
|
'call_type' => $call_type
|
|
], 200);
|
|
}
|
|
|
|
|
|
public function startRecording(Appointment $appointment)
|
|
{
|
|
$telemed = Telemedpro::find($appointment->telemed_pros_id);
|
|
if ($telemed->recording_switch == 0) {
|
|
return response()->json([
|
|
'message' => "Recording Off",
|
|
'Response' => 'Error',
|
|
], 200);
|
|
}
|
|
$roomName = 'appointment-' . $appointment->id;
|
|
$video_token = md5(rand(100000000, 999999999) . rand(1, 9));
|
|
$appointment->video_token = $video_token;
|
|
$appointment->save();
|
|
|
|
$client = new EgressServiceClient("https://plugnmeet.codelfi.com", config('app.LK_API_KEY'), config('app.LK_API_SECRET'));
|
|
try {
|
|
$info = $client->startRoomCompositeEgress($roomName, 'speaker', new EncodedFileOutput([
|
|
"filepath" => "/out/recordings/" . $video_token . ".mp4",
|
|
"file_type" => EncodedFileType::MP4,
|
|
]));
|
|
} catch (Exception $e) {
|
|
return response()->json([
|
|
'message' => $e->getMessage(),
|
|
'Response' => 'Error',
|
|
], 200);
|
|
}
|
|
return response()->json([
|
|
'message' => "Success",
|
|
'Response' => 'Success',
|
|
], 200);
|
|
}
|
|
public function bookAppointmentApi($appointment, $availableTelemedPros)
|
|
{
|
|
$roomName = 'appointment-' . $appointment->id . "-" . uniqid();
|
|
$opts = (new RoomCreateOptions())
|
|
->setName($roomName)
|
|
->setEmptyTimeout(30)
|
|
->setMaxParticipants(5);
|
|
$host = "https://plugnmeet.codelfi.com";
|
|
$svc = new RoomServiceClient($host, config('app.LK_API_KEY'), config('app.LK_API_SECRET'));
|
|
try {
|
|
$svc->deleteRoom($roomName);
|
|
} catch (Exception | Error $e) {
|
|
}
|
|
|
|
$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 endCall($patient_id, $appointment_id)
|
|
{
|
|
$appointment = Appointment::find($appointment_id);
|
|
$appointment->in_call = 0;
|
|
$appointment->end_time = Carbon::now()->format('Y-m-d H:i:s');
|
|
$appointment->save();
|
|
|
|
event(new AppointmentCallEnded($patient_id, $appointment->id));
|
|
|
|
return response()->json([
|
|
'message' => 'Call ended',
|
|
'appointment_id' => $appointment->id,
|
|
], 200);
|
|
}
|
|
|
|
public function searchLabsByAddress(Request $request)
|
|
{
|
|
$address = $request->input('address');
|
|
|
|
try {
|
|
$labs = Lab::where('address', 'like', '%' . $address . '%')
|
|
->orWhere('city', 'like', '%' . $address . '%')
|
|
->orWhere('state', 'like', '%' . $address . '%')
|
|
->orWhere('zip_code', 'like', '%' . $address . '%')
|
|
->get(['id', 'name', 'city', 'state', 'zip_code', 'lang', 'lat']);
|
|
|
|
return response()->json($labs, 200);
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => 'Failed to search labs'], 500);
|
|
}
|
|
}
|
|
public function bookAppointment(Request $request)
|
|
{
|
|
$validatedData = $request->validate([
|
|
'telemed_pros_id' => 'required|exists:telemed_pros,id',
|
|
'patient_id' => 'required|exists:patients,id',
|
|
'doctor_id' => 'required|exists:doctors,id',
|
|
'appointment_id' => 'required',
|
|
'appointment_time' => 'required|date_format:Y-m-d H:i:s',
|
|
]);
|
|
|
|
$appointment = DoctorAppointment::create($validatedData);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
'message' => 'Appointment booked successfully',
|
|
'meeting_id' => $appointment->meeting_id,
|
|
'appointment_time' => $validatedData['appointment_time']
|
|
]);
|
|
}
|
|
public function updateInfo(Request $request, $patientId)
|
|
{
|
|
try {
|
|
$patient = Patient::find($patientId);
|
|
$patient->update($request->only(['city', 'state', 'address', 'zip_code', 'dob', 'country']));
|
|
$patient->save();
|
|
|
|
return response()->json(['message' => 'Patient address updated successfully'], 200);
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => $e->getMessage()], 400);
|
|
}
|
|
}
|
|
public function getInfo(Request $request, $patientId)
|
|
{
|
|
try {
|
|
$patient = Patient::find($patientId)->makeHidden(['password', 'remember_token']);
|
|
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;
|
|
}
|
|
|
|
return response()->json($patient);
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => $e->getMessage()], 400);
|
|
}
|
|
}
|
|
public function getDoctorList()
|
|
{
|
|
try {
|
|
// Fetch only the necessary columns for efficiency
|
|
$doctors = Doctor::select('id', 'name', 'designation')->get()->makeHidden(['password', 'remember_token']);
|
|
|
|
// Return a successful JSON response with the doctors
|
|
return response()->json($doctors, 200);
|
|
} catch (\Exception $e) {
|
|
// Handle exceptions gracefully
|
|
return response()->json(['error' => $e->getMessage()], 500);
|
|
}
|
|
}
|
|
public function getAppointmentList()
|
|
{
|
|
try {
|
|
$appointments = Appointment::select("patients.first_name", "patients.last_name", "telemed_pros.name as agent_name", "appointments.*") // Eager load the associated telemed pro
|
|
->leftJoin("telemed_pros", "telemed_pros.id", "appointments.telemed_pros_id")
|
|
->leftJoin("patients", "patients.id", "appointments.patient_id")
|
|
/* ->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 getDoctorAppointmentList()
|
|
{
|
|
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")
|
|
->orderBy('doctor_appointments.created_at', '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 availableSlots($date)
|
|
{
|
|
// Ensure date is in a valid format
|
|
$date = Carbon::parse($date);
|
|
|
|
// Generate all possible 30-minute slots between 9 AM and 4 PM
|
|
$slots = collect();
|
|
$startTime = Carbon::parse($date)->setTime(9, 0, 0);
|
|
$endTime = Carbon::parse($date)->setTime(16, 0, 0);
|
|
while ($startTime < $endTime) {
|
|
$slots->push($startTime->format('Y-m-d H:i:s'));
|
|
$startTime->addMinutes(30);
|
|
}
|
|
// Filter out booked slots
|
|
$bookedAppointments = Appointment::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);
|
|
|
|
// Add AM/PM
|
|
$startTime = $start->format('g:i A');
|
|
|
|
$end = (clone $start)->addMinutes(29);
|
|
|
|
// Add AM/PM
|
|
$endTime = $end->format('g:i A');
|
|
|
|
return $startTime /* . ' - ' . $endTime */;
|
|
});
|
|
|
|
// Additional checking if slot is booked
|
|
$formattedSlots = $formattedSlots->filter(function ($slot) {
|
|
|
|
$startTime = Carbon::parse($slot);
|
|
/*$startTime = Carbon::parse(explode(' - ', $slot)[0]);
|
|
$endTime = Carbon::parse(explode(' - ', $slot)[1]); */
|
|
|
|
//return !Appointment::whereBetween('appointment_time', [$startTime/* , $endTime */])->exists();
|
|
return !Appointment::where('appointment_time', $startTime)->exists();
|
|
});
|
|
|
|
return response()->json([
|
|
'available_slots' => $formattedSlots->toArray()
|
|
]);
|
|
}
|
|
public function appointmentDetail(Appointment $appointment)
|
|
{
|
|
$patient = Patient::find($appointment->patient_id);
|
|
$telemedPro = Telemedpro::find($appointment->telemed_pros_id);
|
|
$doctor_appointment = DoctorAppointment::select("id", "appointment_date", "appointment_time", "appointment_id")->where('appointment_id', $appointment->id)->first();
|
|
if (!$doctor_appointment)
|
|
$doctor_appointment = [];
|
|
else
|
|
$doctor_appointment = $doctor_appointment->toArray();
|
|
|
|
if ($patient) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
return response()->json([
|
|
'patient' => $patient->toArray() ?? [],
|
|
'telemedPro' => $telemedPro->toArray() ?? [],
|
|
'doctor_appointment' => $doctor_appointment ?? [],
|
|
'agent_appointment' => $appointment,
|
|
'video_url' => "https://plugnmeet.codelfi.com/recordings/" . $appointment->video_token . ".mp4",
|
|
]);
|
|
}
|
|
public function labDetail(Appointment $appointment)
|
|
{
|
|
$lab = Lab::where("appointment_id", $appointment->id)->first();
|
|
return response()->json([
|
|
'lab_name' => $lab->name,
|
|
'lab_address' => $lab->address,
|
|
'lab_city' => $lab->city,
|
|
'lab_state' => $lab->state,
|
|
'lab_distance' => $lab->distance,
|
|
'lab_contact_no' => $lab->contact_no,
|
|
'lab_lang' => $lab->lang,
|
|
'lab_lat' => $lab->lat,
|
|
'slot_date' => $lab->slot_date,
|
|
'slot_time' => $lab->slot_time,
|
|
'booking_time' => $lab->booking_time,
|
|
]);
|
|
}
|
|
public function getRoomList()
|
|
{
|
|
$svc = new RoomServiceClient("https://plugnmeet.codelfi.com", config('app.LK_API_KEY'), config('app.LK_API_SECRET'));
|
|
|
|
// List rooms.
|
|
$rooms = $svc->listRooms();
|
|
|
|
dd($rooms);
|
|
}
|
|
|
|
public function addNotePatient(Request $request)
|
|
{
|
|
// Validation (adjust as needed)
|
|
|
|
$patient = Auth::guard('patient')->user();
|
|
|
|
$addNotePatient = PatientNote::create([
|
|
'note' => $request->input('note'),
|
|
'note_type' => $request->input('note_type'),
|
|
'patient_id' => $patient->id,
|
|
]);
|
|
|
|
return response()->json([
|
|
'message' => 'Note created',
|
|
'data' => $addNotePatient
|
|
], 200);
|
|
}
|
|
|
|
public function getNotePatient(Request $request)
|
|
{
|
|
// Validation (adjust as needed)
|
|
|
|
$patient = Auth::guard('patient')->user();
|
|
|
|
$addNotePatient = PatientNote::where("patient_id", $patient->id)->get();
|
|
|
|
return response()->json([
|
|
'message' => 'Note created',
|
|
'data' => $addNotePatient
|
|
], 200);
|
|
}
|
|
public function markAppointmentsStatus($id)
|
|
{
|
|
$appointment = Appointment::find($id);
|
|
$appointment->status = 'completed';
|
|
$appointment->save();
|
|
return response()->json([
|
|
'message' => 'status updated !'
|
|
], 200);
|
|
}
|
|
}
|