update the app

This commit is contained in:
root
2026-05-25 15:56:00 -04:00
parent 277db06d26
commit 7ca43ba2f3
19 changed files with 1854 additions and 210 deletions
+29 -11
View File
@@ -3,21 +3,39 @@ import 'dart:io';
class AppConstants {
static const String apiBaseUrlOverride =
String.fromEnvironment('API_BASE_URL');
static const String developmentAndroidApiUrl = 'http://10.0.2.2:4000/api/v1';
static const String developmentLocalApiUrl = 'http://localhost:4000/api/v1';
static const String dashboardUrlOverride =
String.fromEnvironment('DASHBOARD_URL');
// Production
static const String productionApiUrl = 'https://api.rentaldrivego.ma/api/v1';
static const String productionDashboardUrl = 'https://rentaldrivego.ma/dashboard';
// Development
static const String devAndroidApiUrl = 'http://10.0.2.2:4000/api/v1';
static const String devLocalApiUrl = 'http://localhost:4000/api/v1';
static const String devAndroidDashboardUrl = 'http://10.0.2.2:3001';
static const String devLocalDashboardUrl = 'http://localhost:3001';
// Dev builds stay local by default. Real phones still need a LAN-reachable
// override because their localhost is the phone itself, not the dev machine.
static String get baseUrl {
if (apiBaseUrlOverride.isNotEmpty) {
return apiBaseUrlOverride;
}
if (apiBaseUrlOverride.isNotEmpty) return apiBaseUrlOverride;
if (Platform.isAndroid) return devAndroidApiUrl;
return devLocalApiUrl;
}
if (Platform.isAndroid) {
return developmentAndroidApiUrl;
}
static String get dashboardBaseUrl {
if (dashboardUrlOverride.isNotEmpty) return dashboardUrlOverride;
if (Platform.isAndroid) return devAndroidDashboardUrl;
return devLocalDashboardUrl;
}
return developmentLocalApiUrl;
static String resolveMediaUrl(String url) {
if (!url.startsWith('http')) {
return '${baseUrl.replaceAll('/api/v1', '')}$url';
}
if (Platform.isAndroid && url.contains('localhost')) {
return url.replaceFirst('localhost', '10.0.2.2');
}
return url;
}
static const String tokenKey = 'auth_token';
+49 -1
View File
@@ -10,10 +10,13 @@ import '../../features/auth/screens/employee_login_screen.dart';
import '../../features/dashboard/screens/home_screen.dart';
import '../../features/dashboard/screens/vehicles_screen.dart';
import '../../features/dashboard/screens/vehicle_detail_screen.dart';
import '../../features/dashboard/screens/vehicle_form_screen.dart';
import '../../features/dashboard/screens/reservations_screen.dart';
import '../../features/dashboard/screens/reservation_detail_screen.dart';
import '../../features/dashboard/screens/new_reservation_screen.dart';
import '../../features/dashboard/screens/customers_screen.dart';
import '../../features/dashboard/screens/customer_detail_screen.dart';
import '../../features/dashboard/screens/customer_form_screen.dart';
import '../../features/dashboard/screens/notifications_screen.dart';
import '../../features/dashboard/screens/online_reservations_screen.dart';
import '../../features/dashboard/screens/contract_screen.dart';
@@ -25,7 +28,10 @@ import '../../features/dashboard/screens/team_screen.dart';
import '../../features/client/screens/client_home_screen.dart';
import '../../features/client/screens/client_vehicle_detail_screen.dart';
import '../../features/client/screens/booking_screen.dart';
import '../../features/client/screens/booking_confirmation_screen.dart';
import '../../features/client/screens/my_bookings_screen.dart';
import '../../features/client/models/booking_result.dart';
import '../../features/agency_webview/screens/agency_dashboard_webview_screen.dart';
final routerProvider = Provider<GoRouter>((ref) {
final router = GoRouter(
@@ -52,7 +58,13 @@ final routerProvider = Provider<GoRouter>((ref) {
}
if (status == AuthStatus.unauthenticated) {
if (isLanding || isLogin || loc.startsWith('/client')) return null;
if (isLanding ||
isLogin ||
loc.startsWith('/client') ||
loc == '/role' ||
loc == '/agency') {
return null;
}
return '/landing';
}
@@ -156,6 +168,42 @@ final routerProvider = Provider<GoRouter>((ref) {
vehicle: state.extra as MarketplaceVehicle?,
),
),
GoRoute(
path: '/booking-confirmation',
builder: (_, state) {
final result = state.extra as BookingResult?;
if (result == null) return const ClientHomeScreen();
return BookingConfirmationScreen(result: result);
},
),
GoRoute(
path: '/agency',
builder: (context, _) => const AgencyDashboardWebViewScreen(),
),
GoRoute(
path: '/dashboard/reservations/new',
builder: (context, _) => const NewReservationScreen(),
),
GoRoute(
path: '/dashboard/vehicles/new',
builder: (context, _) => const VehicleFormScreen(),
),
GoRoute(
path: '/dashboard/vehicles/:id/edit',
builder: (_, state) => VehicleFormScreen(
vehicle: state.extra as dynamic,
),
),
GoRoute(
path: '/dashboard/customers/new',
builder: (context, _) => const CustomerFormScreen(),
),
GoRoute(
path: '/dashboard/customers/:id/edit',
builder: (_, state) => CustomerFormScreen(
customer: state.extra as dynamic,
),
),
],
);
+6
View File
@@ -34,6 +34,12 @@ class ApiClient {
handler.next(response);
},
onError: (e, handler) {
// Log API errors to help diagnose issues during development.
final resp = e.response;
if (resp != null) {
// ignore: avoid_print
print('[API] ${e.requestOptions.method} ${e.requestOptions.path}${resp.statusCode}: ${resp.data}');
}
handler.next(e);
},
));
+4 -2
View File
@@ -74,7 +74,8 @@ class MarketplaceService {
required String firstName,
required String lastName,
required String email,
String? phone,
required String phone,
required String driverLicense,
required DateTime startDate,
required DateTime endDate,
String? notes,
@@ -86,7 +87,8 @@ class MarketplaceService {
'firstName': firstName,
'lastName': lastName,
'email': email,
if (phone != null && phone.isNotEmpty) 'phone': phone,
'phone': phone,
'driverLicense': driverLicense,
'startDate': '${startDate.toIso8601String().substring(0, 10)}T00:00:00.000Z',
'endDate': '${endDate.toIso8601String().substring(0, 10)}T00:00:00.000Z',
if (notes != null && notes.isNotEmpty) 'notes': notes,