631 lines
26 KiB
PHP
631 lines
26 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Ride;
|
|
use App\Models\Driver;
|
|
use App\Models\DriverToken;
|
|
use App\Models\PassengerToken;
|
|
use App\Models\DriverOrder;
|
|
use App\Models\CarLocation;
|
|
use App\Services\LegacyEncryption;
|
|
use App\Services\FcmService;
|
|
use App\Services\SocketService;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class RideController extends Controller
|
|
{
|
|
private LegacyEncryption $encryption;
|
|
private FcmService $fcm;
|
|
private SocketService $socket;
|
|
|
|
public function __construct(LegacyEncryption $encryption, FcmService $fcm, SocketService $socket)
|
|
{
|
|
$this->encryption = $encryption;
|
|
$this->fcm = $fcm;
|
|
$this->socket = $socket;
|
|
}
|
|
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
// 1. Validation (Adding new required fields for the 33-item array)
|
|
$request->validate([
|
|
'start_location' => 'required|string',
|
|
'end_location' => 'required|string',
|
|
'price' => 'required|numeric|min:0',
|
|
'car_type' => 'required|string',
|
|
'distance' => 'required|numeric',
|
|
'price_for_driver' => 'nullable|numeric|min:0',
|
|
'price_for_passenger' => 'nullable|numeric|min:0',
|
|
'status' => 'nullable|string',
|
|
|
|
// Socket / Legacy array specific fields
|
|
'passenger_name' => 'nullable|string',
|
|
'passenger_phone' => 'nullable|string',
|
|
'passenger_token' => 'nullable|string',
|
|
'passenger_email' => 'nullable|string',
|
|
'passenger_wallet' => 'nullable|string',
|
|
'passenger_rating' => 'nullable|string',
|
|
|
|
'start_name' => 'nullable|string',
|
|
'end_name' => 'nullable|string',
|
|
'duration_text' => 'nullable|string',
|
|
'distance_text' => 'nullable|string',
|
|
'is_wallet' => 'nullable|string',
|
|
'has_steps' => 'nullable|string',
|
|
|
|
'step0' => 'nullable|string',
|
|
'step1' => 'nullable|string',
|
|
'step2' => 'nullable|string',
|
|
'step3' => 'nullable|string',
|
|
'step4' => 'nullable|string',
|
|
]);
|
|
|
|
$passengerId = $request->attributes->get('_jwt_user_id');
|
|
|
|
$activeRide = DB::connection('ride')->table('ride')
|
|
->where('passenger_id', $passengerId)
|
|
->whereIn('status', ['waiting', 'going_to_passenger', 'arrived', 'started', 'Begin'])
|
|
->first();
|
|
|
|
if ($activeRide) {
|
|
return response()->json([
|
|
'status' => 'failure',
|
|
'message' => 'You already have an active ride',
|
|
], 409);
|
|
}
|
|
|
|
$rideData = [
|
|
'start_location' => $request->input('start_location'),
|
|
'end_location' => $request->input('end_location'),
|
|
'date' => now()->toDateString(),
|
|
'time' => now()->toTimeString(),
|
|
'endtime' => '00:00:00',
|
|
'price' => $request->input('price'),
|
|
'passenger_id' => $passengerId,
|
|
'driver_id' => '0',
|
|
'status' => $request->input('status', 'waiting'),
|
|
'carType' => $request->input('car_type', 'Speed'),
|
|
'price_for_driver' => $request->input('price_for_driver', $request->input('price')),
|
|
'price_for_passenger' => $request->input('price_for_passenger', $request->input('price')),
|
|
'distance' => $request->input('distance'),
|
|
];
|
|
|
|
DB::connection('primary')->beginTransaction();
|
|
DB::connection('ride')->beginTransaction();
|
|
|
|
try {
|
|
$insertedId = DB::connection('primary')->table('ride')->insertGetId($rideData);
|
|
|
|
$rideData['id'] = $insertedId;
|
|
DB::connection('ride')->table('ride')->insert($rideData);
|
|
|
|
DB::connection('primary')->commit();
|
|
DB::connection('ride')->commit();
|
|
|
|
// Prepare Legacy Array [0..33]
|
|
$partsStart = explode(',', $request->input('start_location'));
|
|
$startLat = trim($partsStart[0] ?? "");
|
|
$startLng = trim($partsStart[1] ?? "");
|
|
|
|
$partsEnd = explode(',', $request->input('end_location'));
|
|
$endLat = trim($partsEnd[0] ?? "");
|
|
$endLng = trim($partsEnd[1] ?? "");
|
|
|
|
$price = (float) $request->input('price');
|
|
$priceForDriver = (float) $request->input('price_for_driver', $price);
|
|
$kazan = $price - $priceForDriver;
|
|
|
|
$payloadTemplate = [];
|
|
$payloadTemplate[0] = (string)$startLat;
|
|
$payloadTemplate[1] = (string)$startLng;
|
|
$payloadTemplate[2] = (string)number_format($price, 2, '.', '');
|
|
$payloadTemplate[3] = (string)$endLat;
|
|
$payloadTemplate[4] = (string)$endLng;
|
|
$payloadTemplate[5] = (string)$request->input('distance_text', '');
|
|
$payloadTemplate[6] = "";
|
|
$payloadTemplate[7] = (string)$passengerId;
|
|
$payloadTemplate[8] = (string)$request->input('passenger_name', '');
|
|
$payloadTemplate[9] = (string)$request->input('passenger_token', '');
|
|
$payloadTemplate[10] = (string)$request->input('passenger_phone', '');
|
|
$payloadTemplate[11] = (string)$request->input('distance', '0');
|
|
$payloadTemplate[12] = "1";
|
|
$payloadTemplate[13] = (string)$request->input('is_wallet', '0');
|
|
$payloadTemplate[14] = (string)$request->input('distance', '0');
|
|
$payloadTemplate[15] = (string)$request->input('duration_text', '');
|
|
$payloadTemplate[16] = (string)$insertedId;
|
|
$payloadTemplate[17] = "";
|
|
$payloadTemplate[18] = "";
|
|
$payloadTemplate[19] = (string)$request->input('duration_text', '');
|
|
$payloadTemplate[20] = $request->input('has_steps') ?: 'false';
|
|
$payloadTemplate[21] = (string)$request->input('step0', '');
|
|
$payloadTemplate[22] = (string)$request->input('step1', '');
|
|
$payloadTemplate[23] = (string)$request->input('step2', '');
|
|
$payloadTemplate[24] = (string)$request->input('step3', '');
|
|
$payloadTemplate[25] = (string)$request->input('step4', '');
|
|
$payloadTemplate[26] = (string)number_format($priceForDriver, 2, '.', '');
|
|
$payloadTemplate[27] = (string)$request->input('passenger_wallet', '0');
|
|
$payloadTemplate[28] = (string)$request->input('passenger_email', '');
|
|
$payloadTemplate[29] = (string)$request->input('start_name', '');
|
|
$payloadTemplate[30] = (string)$request->input('end_name', '');
|
|
$payloadTemplate[31] = (string)$request->input('car_type', 'Speed');
|
|
$payloadTemplate[32] = (string)number_format($kazan, 2, '.', '');
|
|
$payloadTemplate[33] = (string)$request->input('passenger_rating', '5.0');
|
|
|
|
ksort($payloadTemplate);
|
|
$payloadArray = array_values($payloadTemplate);
|
|
|
|
// Send to Market exactly like V1
|
|
$this->socket->sendToLocationServer('market_new_ride', [
|
|
'payload' => $payloadArray
|
|
]);
|
|
|
|
return response()->json([
|
|
'status' => 'success',
|
|
'data' => $insertedId,
|
|
], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
DB::connection('primary')->rollBack();
|
|
DB::connection('ride')->rollBack();
|
|
\Log::error('AddRide Critical Error: ' . $e->getMessage());
|
|
return response()->json([
|
|
'status' => 'failure',
|
|
'message' => 'Failed to add ride',
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function accept(Request $request, int $rideId): JsonResponse
|
|
{
|
|
$driverId = $request->attributes->get('_jwt_user_id');
|
|
$status = $request->input('status', 'Apply'); // Allow dynamic status but default to Apply
|
|
|
|
DB::connection('ride')->beginTransaction();
|
|
try {
|
|
$ride = Ride::lockForUpdate()->find($rideId);
|
|
|
|
if (!$ride || !in_array($ride->status, ['waiting', 'wait'])) {
|
|
DB::connection('ride')->rollBack();
|
|
return response()->json([
|
|
'status' => 'failure',
|
|
'message' => 'Ride not available (Already taken)',
|
|
], 409); // Keep 409 for conflict but failure text from V1
|
|
}
|
|
|
|
// Remote DB Update
|
|
$ride->update([
|
|
'driver_id' => $driverId,
|
|
'status' => $status,
|
|
'rideTimeStart' => now(), // V1 acceptRide does this
|
|
'DriverIsGoingToPassenger' => now(),
|
|
]);
|
|
|
|
// Local DB Update
|
|
DB::connection('primary')
|
|
->table('ride')
|
|
->where('id', $rideId)
|
|
->update([
|
|
'driver_id' => $driverId,
|
|
'status' => $status,
|
|
'rideTimeStart' => now(),
|
|
]);
|
|
|
|
// Remove from waiting rides (legacy)
|
|
DB::connection('primary')
|
|
->table('waitingRides')
|
|
->where('id', (string) $rideId)
|
|
->update(['status' => $status]);
|
|
|
|
// Driver Orders
|
|
$checkOrder = DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)->first();
|
|
if ($checkOrder) {
|
|
DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)
|
|
->update(['driver_id' => $driverId, 'status' => $status, 'created_at' => now()]);
|
|
} else {
|
|
DB::connection('primary')->table('driver_orders')
|
|
->insert(['driver_id' => $driverId, 'order_id' => (string)$rideId, 'status' => $status, 'created_at' => now()]);
|
|
}
|
|
|
|
DB::connection('ride')->commit();
|
|
|
|
// Fetch Driver Info for Passenger
|
|
$driverRaw = DB::connection('primary')
|
|
->table('driver as d')
|
|
->leftJoin('CarRegistration as c', 'c.driverID', '=', 'd.id')
|
|
->leftJoin('driverToken as dt', 'dt.captain_id', '=', 'd.id')
|
|
->leftJoin('ratingDriver as r', 'r.driver_id', '=', 'd.id')
|
|
->select(
|
|
'd.id as driver_id', 'd.first_name', 'd.last_name', 'd.gender', 'd.phone',
|
|
'c.make', 'c.model', 'c.car_plate', 'c.year', 'c.color', 'c.color_hex',
|
|
'dt.token', DB::raw('ROUND(AVG(r.rating), 2) as ratingDriver')
|
|
)
|
|
->where('d.id', $driverId)
|
|
->groupBy('d.id', 'd.first_name', 'd.last_name', 'd.gender', 'd.phone', 'c.make', 'c.model', 'c.car_plate', 'c.year', 'c.color', 'c.color_hex', 'dt.token')
|
|
->first();
|
|
|
|
$driverInfo = [];
|
|
if ($driverRaw) {
|
|
$fieldsToDecrypt = ['first_name', 'last_name', 'gender', 'phone', 'car_plate', 'token'];
|
|
foreach ((array)$driverRaw as $key => $value) {
|
|
if (in_array($key, $fieldsToDecrypt) && !empty($value)) {
|
|
$driverInfo[$key] = $this->encryption->decrypt($value);
|
|
} else {
|
|
$driverInfo[$key] = $value;
|
|
}
|
|
}
|
|
$driverInfo['driverName'] = trim(($driverInfo['first_name'] ?? '') . ' ' . ($driverInfo['last_name'] ?? ''));
|
|
if (empty($driverInfo['ratingDriver'])) {
|
|
$driverInfo['ratingDriver'] = "5.0";
|
|
}
|
|
}
|
|
|
|
// Notify passenger via socket
|
|
$this->socket->notifyPassenger($ride->passenger_id, [
|
|
'ride_id' => $rideId,
|
|
'status' => 'accepted', // App uses 'accepted'
|
|
'driver_id' => $driverId,
|
|
'driver_info' => $driverInfo
|
|
]);
|
|
|
|
// Notify passenger via FCM
|
|
$passengerToken = PassengerToken::where('passengerID', $ride->passenger_id)->first();
|
|
if ($passengerToken) {
|
|
$decryptedToken = $this->encryption->decrypt($passengerToken->token);
|
|
$this->fcm->sendToDevice(
|
|
$decryptedToken,
|
|
"Ride Accepted 🚖",
|
|
"Captain " . ($driverInfo['driverName'] ?? 'Driver') . " is coming to you.",
|
|
['ride_id' => (string) $rideId, 'driver_info' => $driverInfo],
|
|
'Accepted Ride'
|
|
);
|
|
}
|
|
|
|
// Cleanup Marketplace
|
|
$this->socket->sendToLocationServer('ride_taken_event', [
|
|
'ride_id' => $rideId,
|
|
'taken_by_driver_id' => $driverId
|
|
]);
|
|
|
|
return response()->json([
|
|
'status' => 'success',
|
|
'message' => 'Ride Accepted',
|
|
'data' => $driverInfo
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
DB::connection('ride')->rollBack();
|
|
return response()->json(['status' => 'failure', 'message' => 'Error: ' . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
public function arrive(Request $request, int $rideId): JsonResponse
|
|
{
|
|
$driverId = $request->attributes->get('_jwt_user_id');
|
|
|
|
$ride = Ride::where('id', $rideId)->where('driver_id', $driverId)->whereIn('status', ['Apply', 'Applied'])->first();
|
|
|
|
if (!$ride) {
|
|
return response()->json(['status' => 'failure', 'message' => 'Ride not found'], 404);
|
|
}
|
|
|
|
$ride->update(['status' => 'arrived']); // Matching V1 lowercase
|
|
|
|
DB::connection('primary')->table('ride')->where('id', $rideId)->update(['status' => 'arrived', 'updated_at' => now()]);
|
|
|
|
// Socket
|
|
$this->socket->notifyPassenger($ride->passenger_id, [
|
|
'status' => 'arrived',
|
|
'ride_id' => $rideId,
|
|
'msg' => 'السائق وصل إلى موقعك 🚖'
|
|
]);
|
|
|
|
// FCM
|
|
$passengerToken = PassengerToken::where('passengerID', $ride->passenger_id)->first();
|
|
if ($passengerToken) {
|
|
$this->fcm->sendToDevice(
|
|
$this->encryption->decrypt($passengerToken->token),
|
|
"السائق وصل 📍",
|
|
"الكابتن ينتظرك في الموقع المحدد.",
|
|
['ride_id' => (string) $rideId],
|
|
'Arrive Ride'
|
|
);
|
|
}
|
|
|
|
return response()->json(['status' => 'success', 'message' => 'Arrival notified successfully']);
|
|
}
|
|
|
|
public function start(Request $request, int $rideId): JsonResponse
|
|
{
|
|
$driverId = $request->attributes->get('_jwt_user_id');
|
|
$status = 'Begin';
|
|
|
|
$ride = Ride::where('id', $rideId)->where('driver_id', $driverId)->whereIn('status', ['Apply', 'Applied', 'arrived', 'Arrived'])->first();
|
|
|
|
if (!$ride) {
|
|
return response()->json(['status' => 'failure', 'message' => 'Ride not found or not ready'], 404);
|
|
}
|
|
|
|
$ride->update(['status' => $status, 'rideTimeStart' => now()]);
|
|
DB::connection('primary')->table('ride')->where('id', $rideId)->update(['status' => $status, 'rideTimeStart' => now()]);
|
|
|
|
// Driver Orders
|
|
$checkOrder = DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)->first();
|
|
if ($checkOrder) {
|
|
DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)->update(['driver_id' => $driverId, 'status' => $status, 'created_at' => now()]);
|
|
} else {
|
|
DB::connection('primary')->table('driver_orders')->insert(['driver_id' => $driverId, 'order_id' => (string)$rideId, 'status' => $status, 'created_at' => now()]);
|
|
}
|
|
|
|
// Socket
|
|
$this->socket->notifyPassenger($ride->passenger_id, [
|
|
'ride_id' => $rideId,
|
|
'status' => 'started',
|
|
'msg' => 'بدأت الرحلة، نتمنى لك سلامة الوصول 🚀'
|
|
]);
|
|
|
|
// FCM
|
|
$passengerToken = PassengerToken::where('passengerID', $ride->passenger_id)->first();
|
|
if ($passengerToken) {
|
|
$this->fcm->sendToDevice(
|
|
$this->encryption->decrypt($passengerToken->token),
|
|
"بدأت الرحلة 🏁",
|
|
"نتمنى لك رحلة آمنة ومريحة.",
|
|
['ride_id' => (string) $rideId],
|
|
'Trip is Begin'
|
|
);
|
|
}
|
|
|
|
return response()->json(['status' => 'success', 'message' => 'Ride started successfully']);
|
|
}
|
|
|
|
public function finish(Request $request, int $rideId): JsonResponse
|
|
{
|
|
$driverId = $request->attributes->get('_jwt_user_id');
|
|
$price = $request->input('price', 0);
|
|
$status = 'Finished';
|
|
|
|
$ride = Ride::where('id', $rideId)->where('driver_id', $driverId)->where('status', 'Begin')->first();
|
|
|
|
if (!$ride) {
|
|
return response()->json(['status' => 'failure', 'message' => 'Ride not found'], 404);
|
|
}
|
|
|
|
DB::connection('ride')->beginTransaction();
|
|
try {
|
|
$ride->update([
|
|
'status' => $status,
|
|
'rideTimeFinish' => now(),
|
|
'endtime' => now()->toTimeString(),
|
|
'price' => $price,
|
|
]);
|
|
|
|
DB::connection('primary')->table('ride')->where('id', $rideId)->update([
|
|
'status' => $status,
|
|
'rideTimeFinish' => now(),
|
|
'price' => $price,
|
|
]);
|
|
|
|
// Driver Orders
|
|
$checkOrder = DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)->first();
|
|
if ($checkOrder) {
|
|
DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)->update(['driver_id' => $driverId, 'status' => $status, 'created_at' => now()]);
|
|
} else {
|
|
DB::connection('primary')->table('driver_orders')->insert(['driver_id' => $driverId, 'order_id' => (string)$rideId, 'status' => $status, 'created_at' => now()]);
|
|
}
|
|
|
|
// Get Driver Token for LegacyList
|
|
$driverTokenRaw = DB::connection('primary')->table('driverToken')->where('captain_id', $driverId)->value('token');
|
|
$driverTokenDecrypted = $driverTokenRaw ? $this->encryption->decrypt($driverTokenRaw) : '';
|
|
|
|
$legacyList = [
|
|
(string)$driverId,
|
|
(string)$rideId,
|
|
(string)$driverTokenDecrypted,
|
|
(string)$price
|
|
];
|
|
|
|
DB::connection('ride')->commit();
|
|
|
|
// Socket
|
|
$this->socket->notifyPassenger($ride->passenger_id, [
|
|
'ride_id' => $rideId,
|
|
'status' => 'finished',
|
|
'price' => $price,
|
|
'DriverList' => $legacyList
|
|
]);
|
|
|
|
// FCM
|
|
$passengerToken = PassengerToken::where('passengerID', $ride->passenger_id)->first();
|
|
if ($passengerToken) {
|
|
$this->fcm->sendToDevice(
|
|
$this->encryption->decrypt($passengerToken->token),
|
|
"تم إنهاء الرحلة 🏁",
|
|
"المبلغ المطلوب: " . $price . " ل.س",
|
|
['ride_id' => (string) $rideId, 'price' => (string) $price, 'DriverList' => $legacyList],
|
|
'Driver Finish Trip'
|
|
);
|
|
}
|
|
|
|
return response()->json(['status' => 'success', 'message' => 'Ride finished successfully']);
|
|
|
|
} catch (\Exception $e) {
|
|
DB::connection('ride')->rollBack();
|
|
return response()->json(['status' => 'failure', 'message' => 'DB Error: ' . $e->getMessage()], 500);
|
|
}
|
|
}
|
|
|
|
public function cancelByPassenger(Request $request, int $rideId): JsonResponse
|
|
{
|
|
$passengerId = $request->attributes->get('_jwt_user_id');
|
|
$reason = $request->input('reason', 'No reason specified');
|
|
|
|
$ride = Ride::where('id', $rideId)->where('passenger_id', $passengerId)->active()->first();
|
|
|
|
if (!$ride) {
|
|
return response()->json(['status' => 'failure', 'message' => 'Ride not found'], 404);
|
|
}
|
|
|
|
if ($ride->status === 'Begin') {
|
|
return response()->json(['status' => 'failure', 'message' => 'Cannot cancel started ride'], 400);
|
|
}
|
|
|
|
$driverId = $ride->driver_id;
|
|
|
|
$ride->update(['status' => 'cancelled_by_passenger']);
|
|
DB::connection('primary')->table('ride')->where('id', $rideId)->update(['status' => 'cancelled_by_passenger', 'updated_at' => now()]);
|
|
DB::connection('primary')->table('waitingRides')->where('id', (string) $rideId)->update(['status' => 'cancelled_by_passenger']);
|
|
|
|
// Driver Orders
|
|
if ($driverId !== 'none' && $driverId != 0) {
|
|
DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)->where('driver_id', $driverId)->update(['status' => 'cancelled_by_passenger', 'notes' => $reason]);
|
|
}
|
|
|
|
// Log cancellation
|
|
DB::connection('ride')->table('canecl')->insert([
|
|
'driverID' => $driverId ?? 'none',
|
|
'passengerID' => $passengerId,
|
|
'rideID' => (string) $rideId,
|
|
'note' => $reason,
|
|
]);
|
|
|
|
if ($driverId !== 'none' && $driverId != 0) {
|
|
// Socket
|
|
$this->socket->sendToLocationServer('cancel_ride', [
|
|
'driver_id' => $driverId,
|
|
'ride_id' => $rideId,
|
|
'reason' => $reason
|
|
]);
|
|
|
|
// FCM
|
|
$driverToken = DriverToken::where('captain_id', $driverId)->first();
|
|
if ($driverToken) {
|
|
$this->fcm->sendToDevice(
|
|
$this->encryption->decrypt($driverToken->token),
|
|
"إلغاء الرحلة 🚫",
|
|
"قام الراكب بإلغاء الرحلة: $reason",
|
|
['ride_id' => (string) $rideId, 'reason' => $reason],
|
|
'Cancel Trip'
|
|
);
|
|
}
|
|
}
|
|
|
|
return response()->json(['status' => 'success', 'message' => 'Ride cancelled successfully']);
|
|
}
|
|
|
|
public function cancelByDriver(Request $request, int $rideId): JsonResponse
|
|
{
|
|
$driverId = $request->attributes->get('_jwt_user_id');
|
|
$reason = $request->input('reason', 'No reason specified');
|
|
|
|
$ride = Ride::where('id', $rideId)->where('driver_id', $driverId)->active()->first();
|
|
|
|
if (!$ride) {
|
|
return response()->json(['status' => 'failure', 'message' => 'Ride not found'], 404);
|
|
}
|
|
|
|
$ride->update(['status' => 'cancelled_by_driver', 'driver_id' => 'none']);
|
|
DB::connection('primary')->table('ride')->where('id', $rideId)->update(['status' => 'cancelled_by_driver']);
|
|
DB::connection('primary')->table('waitingRides')->where('id', (string) $rideId)->update(['status' => 'waiting']);
|
|
|
|
// Driver Orders
|
|
DB::connection('primary')->table('driver_orders')->where('order_id', (string)$rideId)->where('driver_id', $driverId)->update(['status' => 'cancelled_by_driver', 'notes' => $reason]);
|
|
|
|
// Log cancellation
|
|
DB::connection('ride')->table('canecl')->insert([
|
|
'driverID' => $driverId,
|
|
'passengerID' => $ride->passenger_id,
|
|
'rideID' => (string) $rideId,
|
|
'note' => $reason,
|
|
]);
|
|
|
|
// Socket to passenger
|
|
$this->socket->notifyPassenger($ride->passenger_id, [
|
|
'ride_id' => $rideId,
|
|
'status' => 'cancelled_by_driver',
|
|
'reason' => $reason
|
|
]);
|
|
|
|
// FCM to passenger
|
|
$passengerToken = PassengerToken::where('passengerID', $ride->passenger_id)->first();
|
|
if ($passengerToken) {
|
|
$this->fcm->sendToDevice(
|
|
$this->encryption->decrypt($passengerToken->token),
|
|
"إلغاء الرحلة 🚫",
|
|
"قام السائق بإلغاء الرحلة: $reason",
|
|
['ride_id' => (string) $rideId, 'reason' => $reason],
|
|
'Cancel Trip'
|
|
);
|
|
}
|
|
|
|
return response()->json(['status' => 'success', 'message' => 'Ride cancelled successfully']);
|
|
}
|
|
|
|
public function show(Request $request, int $rideId): JsonResponse
|
|
{
|
|
$userId = $request->attributes->get('_jwt_user_id');
|
|
$ride = Ride::where('id', $rideId)
|
|
->where(function($q) use ($userId) {
|
|
$q->where('passenger_id', $userId)
|
|
->orWhere('driver_id', $userId);
|
|
})
|
|
->first();
|
|
|
|
if (!$ride) {
|
|
return response()->json(['status' => 'failure', 'message' => 'Ride not found or access denied'], 404);
|
|
}
|
|
return response()->json(['status' => 'success', 'data' => $ride]);
|
|
}
|
|
|
|
public function active(Request $request): JsonResponse
|
|
{
|
|
$userId = $request->attributes->get('_jwt_user_id');
|
|
$userType = $request->attributes->get('_jwt_user_type');
|
|
|
|
$query = Ride::active();
|
|
if ($userType === 'driver') {
|
|
$query->forDriver($userId);
|
|
} else {
|
|
$query->forPassenger($userId);
|
|
}
|
|
|
|
$ride = $query->orderBy('id', 'desc')->first();
|
|
|
|
return response()->json([
|
|
'status' => 'success',
|
|
'data' => $ride,
|
|
]);
|
|
}
|
|
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$userId = $request->attributes->get('_jwt_user_id');
|
|
$userType = $request->attributes->get('_jwt_user_type');
|
|
$page = $request->input('page', 1);
|
|
$limit = min($request->input('limit', 20), 50);
|
|
|
|
$query = Ride::query();
|
|
if ($userType === 'driver') {
|
|
$query->forDriver($userId);
|
|
} else {
|
|
$query->forPassenger($userId);
|
|
}
|
|
|
|
$rides = $query->orderBy('id', 'desc')
|
|
->skip(($page - 1) * $limit)
|
|
->take($limit)
|
|
->get()
|
|
->map(function ($ride) {
|
|
$ride->order_id = $ride->id;
|
|
$ride->start_name = "Pickup point"; // Simplified for now
|
|
$ride->end_name = "Destination point";
|
|
$ride->price = (string) number_format($ride->price, 0, '.', '');
|
|
return $ride;
|
|
});
|
|
|
|
return response()->json(['status' => 'success', 'data' => $rides, 'message' => $rides]);
|
|
}
|
|
}
|