140 lines
3.4 KiB
Dart
140 lines
3.4 KiB
Dart
import 'dart:convert';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
|
|
import '../../constant/links.dart';
|
|
import '../functions/crud.dart';
|
|
|
|
class RideLookupController extends GetxController {
|
|
final TextEditingController phoneCtrl = TextEditingController();
|
|
|
|
bool isLoading = false;
|
|
Map<String, dynamic>? passenger; // {id, first_name, last_name, phone}
|
|
Map<String, dynamic>? ride; // Ride details
|
|
|
|
// Status filter for the search tab
|
|
String currentStatusFilter = '';
|
|
|
|
// Whitelist of allowed statuses for the Update Dropdown
|
|
// UPDATED: Matches the exact types you requested
|
|
final List<String> statusOptions = const [
|
|
'Pending',
|
|
'Accepted',
|
|
'EnRoute',
|
|
'Arrived',
|
|
'Started',
|
|
'Completed',
|
|
'Canceled',
|
|
];
|
|
|
|
String? selectedStatus;
|
|
|
|
// Hydrate dropdown value from the current ride data
|
|
void hydrateSelectedFromRide() {
|
|
final cur = (ride?['status'] ?? '') as String;
|
|
selectedStatus = statusOptions.contains(cur) ? cur : null;
|
|
update();
|
|
}
|
|
|
|
Future<bool> updateRideStatus({String? note}) async {
|
|
if (ride == null) return false;
|
|
if (selectedStatus == null || selectedStatus!.isEmpty) return false;
|
|
|
|
isLoading = true;
|
|
update();
|
|
|
|
try {
|
|
final res = await CRUD().post(
|
|
link: AppLink.admin_update_ride_status,
|
|
payload: {
|
|
'id': "${ride!['id']}",
|
|
'status': selectedStatus!,
|
|
if (note != null && note.trim().isNotEmpty) 'reason': note.trim(),
|
|
},
|
|
);
|
|
|
|
final d = jsonDecode(res);
|
|
final ok = (d['status'] == 'success');
|
|
|
|
if (ok) {
|
|
// Update local ride details from response
|
|
final updated = (d['message'] ?? d)['ride'];
|
|
if (updated != null) {
|
|
ride = Map<String, dynamic>.from(updated);
|
|
}
|
|
update();
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} catch (_) {
|
|
return false;
|
|
} finally {
|
|
isLoading = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
// Updated to accept status filter
|
|
Future<bool> searchLatest({String? status}) async {
|
|
final phone = phoneCtrl.text.trim();
|
|
|
|
// If status is passed, update the current filter
|
|
if (status != null) {
|
|
currentStatusFilter = status;
|
|
}
|
|
|
|
// If phone is empty, we stop unless your API supports fetching "latest of all users"
|
|
if (phone.isEmpty) {
|
|
return false;
|
|
}
|
|
|
|
isLoading = true;
|
|
update();
|
|
|
|
try {
|
|
final res = await CRUD().post(
|
|
link: AppLink.admin_get_rides_by_phone,
|
|
payload: {
|
|
'phone': phone,
|
|
// If filter is 'All', send empty string to PHP, otherwise send the exact status
|
|
'status': currentStatusFilter == 'All' ? '' : currentStatusFilter,
|
|
},
|
|
);
|
|
|
|
final d = res;
|
|
|
|
if (d['status'] == 'success') {
|
|
passenger = (d['message'] ?? d)['passenger'];
|
|
ride = (d['message'] ?? d)['ride'];
|
|
|
|
// Hydrate the dropdown for the update section based on the fetched ride
|
|
hydrateSelectedFromRide();
|
|
|
|
update();
|
|
return true;
|
|
} else {
|
|
passenger = null;
|
|
ride = null;
|
|
update();
|
|
return false;
|
|
}
|
|
} catch (_) {
|
|
passenger = null;
|
|
ride = null;
|
|
update();
|
|
return false;
|
|
} finally {
|
|
isLoading = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
String rideHeader() {
|
|
if (ride == null) return '';
|
|
final id = ride!['id'] ?? '';
|
|
final st = (ride!['status'] ?? '—').toString();
|
|
return "Ride #$id — $st";
|
|
}
|
|
}
|