feat: standard error handling, web bug fixes, and mock data setup
This commit is contained in:
@@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
@@ -14,10 +15,13 @@ import 'package:doormile/core/theme/app_colors.dart';
|
||||
/// Holds the in-progress booking the user is composing across the flow screens.
|
||||
class BookingDraft {
|
||||
String pickupAddress = '';
|
||||
String pickupPincode = '';
|
||||
double pickupLatitude = 0.0;
|
||||
double pickupLongitude = 0.0;
|
||||
String contactName = '';
|
||||
String contactMobile = '';
|
||||
String notes = '';
|
||||
|
||||
|
||||
String destination = '';
|
||||
String service = '';
|
||||
String parcelType = '';
|
||||
@@ -37,6 +41,9 @@ class BookingDraft {
|
||||
|
||||
void reset() {
|
||||
pickupAddress = '';
|
||||
pickupPincode = '';
|
||||
pickupLatitude = 0.0;
|
||||
pickupLongitude = 0.0;
|
||||
contactName = '';
|
||||
contactMobile = '';
|
||||
notes = '';
|
||||
@@ -71,6 +78,8 @@ class AppState extends ChangeNotifier {
|
||||
String? pendingEmail;
|
||||
String? authToken;
|
||||
bool isResettingPin = false;
|
||||
bool isLoginFlow = false;
|
||||
String? _deviceToken;
|
||||
|
||||
AppState() {
|
||||
_loadSession();
|
||||
@@ -101,6 +110,18 @@ class AppState extends ChangeNotifier {
|
||||
await prefs.setString('phone', phone);
|
||||
}
|
||||
|
||||
Future<String?> _fetchDeviceToken() async {
|
||||
try {
|
||||
if (kIsWeb) return null;
|
||||
await FirebaseMessaging.instance.requestPermission(alert: true, badge: true, sound: true);
|
||||
_deviceToken = await FirebaseMessaging.instance.getToken();
|
||||
return _deviceToken;
|
||||
} catch (e) {
|
||||
debugPrint('FCM token error: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void setPhone(String value) {
|
||||
phone = value;
|
||||
notifyListeners();
|
||||
@@ -195,7 +216,7 @@ class AppState extends ChangeNotifier {
|
||||
|
||||
double lat = 0.0;
|
||||
double lng = 0.0;
|
||||
|
||||
|
||||
try {
|
||||
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (serviceEnabled) {
|
||||
@@ -212,7 +233,9 @@ class AppState extends ChangeNotifier {
|
||||
} catch (e) {
|
||||
debugPrint('Error getting location for registration: $e');
|
||||
}
|
||||
|
||||
|
||||
final token = await _fetchDeviceToken();
|
||||
|
||||
final res = await http.post(
|
||||
Uri.parse(ApiConstants.register),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
@@ -224,7 +247,8 @@ class AppState extends ChangeNotifier {
|
||||
"pin": pin,
|
||||
"configid": 1001,
|
||||
"defaultlatitude": lat,
|
||||
"defaultlongitude": lng
|
||||
"defaultlongitude": lng,
|
||||
if (token != null) "device_token": token,
|
||||
}),
|
||||
);
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
@@ -277,10 +301,17 @@ class AppState extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
|
||||
final token = await _fetchDeviceToken();
|
||||
|
||||
final verifyRes = await http.post(
|
||||
Uri.parse(ApiConstants.verifyPin),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: jsonEncode({"phone": rawPhone, "pin": pin, "configid": 1001}),
|
||||
body: jsonEncode({
|
||||
"phone": rawPhone,
|
||||
"pin": pin,
|
||||
"configid": 1001,
|
||||
if (token != null) "device_token": token,
|
||||
}),
|
||||
);
|
||||
|
||||
if (verifyRes.statusCode >= 200 && verifyRes.statusCode < 300) {
|
||||
@@ -316,8 +347,8 @@ class AppState extends ChangeNotifier {
|
||||
|
||||
void login() {
|
||||
isLoggedIn = true;
|
||||
// Wipe hardcoded mock data so real users only see their own actual data!
|
||||
orders.clear();
|
||||
isLoginFlow = false;
|
||||
orders.clear();
|
||||
savedAddresses.clear();
|
||||
_saveSession();
|
||||
notifyListeners();
|
||||
@@ -326,13 +357,13 @@ class AppState extends ChangeNotifier {
|
||||
Future<void> logout() async {
|
||||
isLoggedIn = false;
|
||||
authToken = null;
|
||||
// Reset in-memory user details so the previous account does not linger.
|
||||
firstName = 'User';
|
||||
userName = 'User';
|
||||
phone = '';
|
||||
verificationId = null;
|
||||
pendingFirstName = null;
|
||||
pendingEmail = null;
|
||||
isLoginFlow = false;
|
||||
orders.clear();
|
||||
savedAddresses.clear();
|
||||
notifyListeners();
|
||||
@@ -360,6 +391,27 @@ class AppState extends ChangeNotifier {
|
||||
isLoadingOrders = true;
|
||||
notifyListeners();
|
||||
|
||||
if (authToken == 'easter-egg-token') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
orders = [
|
||||
Order(
|
||||
id: 'DM-TEST-001',
|
||||
fromLabel: 'Home (Mock)',
|
||||
fromSub: 'Pickup',
|
||||
toLabel: 'Pincode: 110001',
|
||||
toSub: 'Delivery',
|
||||
date: 'Today',
|
||||
amount: 65.0,
|
||||
status: OrderStatus.active,
|
||||
progress: 0.1,
|
||||
eta: '10 min',
|
||||
),
|
||||
];
|
||||
isLoadingOrders = false;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
print('\n=== DOORMILE API FETCH ORDERS ===');
|
||||
print('Endpoint: ${ApiConstants.getPickups}');
|
||||
@@ -425,6 +477,7 @@ class AppState extends ChangeNotifier {
|
||||
final payload = {
|
||||
"zone": "Local",
|
||||
"destinationpin": draft.dropPincode,
|
||||
"pickuppincode": draft.pickupPincode,
|
||||
"service_type": draft.service.isNotEmpty ? draft.service : "Normal",
|
||||
"weight": 1.0, // Default since we removed it from UI
|
||||
"category": backendCategory
|
||||
@@ -435,6 +488,14 @@ class AppState extends ChangeNotifier {
|
||||
print('Payload: ${jsonEncode(payload)}');
|
||||
print('====================================\n');
|
||||
|
||||
if (authToken == 'easter-egg-token') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
draft.minPrice = 50.0;
|
||||
draft.maxPrice = 120.0;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final res = await http.post(
|
||||
Uri.parse(ApiConstants.checkPrice),
|
||||
@@ -480,8 +541,12 @@ class AppState extends ChangeNotifier {
|
||||
|
||||
final payload = {
|
||||
"pickupaddress": draft.pickupAddress.isNotEmpty ? draft.pickupAddress : "Current Location (GPS)",
|
||||
"pickuppincode": "560001", // Default pincode until we parse from GPS
|
||||
"pickuppincode": draft.pickupPincode,
|
||||
"pickuplatitude": draft.pickupLatitude,
|
||||
"pickuplongitude": draft.pickupLongitude,
|
||||
"deliverypincode": draft.dropPincode,
|
||||
"deliveryaddress": draft.dropAddress,
|
||||
"serviceoption": draft.service,
|
||||
"parcels": [
|
||||
{
|
||||
"itemcategory": backendCategory,
|
||||
@@ -495,6 +560,27 @@ class AppState extends ChangeNotifier {
|
||||
print('Payload: ${jsonEncode(payload)}');
|
||||
print('====================================\n');
|
||||
|
||||
if (authToken == 'easter-egg-token') {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
final newOrder = Order(
|
||||
id: 'DM-PU-000${101 + orders.length}',
|
||||
fromLabel: draft.pickupAddress,
|
||||
fromSub: draft.contactName.isEmpty ? 'Pickup requested' : 'Contact: ${draft.contactName}',
|
||||
toLabel: draft.dropPincode.isNotEmpty ? 'Pincode: ${draft.dropPincode}' : 'Awaiting Miler input',
|
||||
toSub: 'Drop details pending',
|
||||
date: 'Today',
|
||||
amount: draft.minPrice,
|
||||
status: OrderStatus.active,
|
||||
progress: 0.1,
|
||||
eta: 'Assigning Miler...',
|
||||
);
|
||||
|
||||
orders.insert(0, newOrder);
|
||||
draft.reset();
|
||||
notifyListeners();
|
||||
return newOrder;
|
||||
}
|
||||
|
||||
final res = await http.post(
|
||||
Uri.parse(ApiConstants.createPickup),
|
||||
headers: {
|
||||
@@ -542,6 +628,7 @@ class AppState extends ChangeNotifier {
|
||||
icon: Icons.home_rounded,
|
||||
iconBg: AppColors.primaryFixed,
|
||||
iconColor: AppColors.primary,
|
||||
pincode: '122003',
|
||||
),
|
||||
AddressEntry(
|
||||
label: 'Work',
|
||||
@@ -549,6 +636,7 @@ class AppState extends ChangeNotifier {
|
||||
icon: Icons.work_rounded,
|
||||
iconBg: AppColors.tertiaryFixed,
|
||||
iconColor: AppColors.tertiary,
|
||||
pincode: '122002',
|
||||
),
|
||||
AddressEntry(
|
||||
label: 'Select City Walk Mall',
|
||||
@@ -556,6 +644,7 @@ class AppState extends ChangeNotifier {
|
||||
icon: Icons.history_rounded,
|
||||
iconBg: AppColors.surfaceContainerHigh,
|
||||
iconColor: AppColors.onSurfaceVariant,
|
||||
pincode: '110017',
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user