voyage 0.0.4-canary.62
voyage: ^0.0.4-canary.62 copied to clipboard
A Flutter plugin for integrating Kruzr 360 trip tracking, driver analytics, and real-time vehicle data communication.
example/lib/main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:voyage/kruzr_360_communicator.dart';
import 'package:voyage/model/kruzr_360_init_config.dart';
import 'package:voyage/model/registered_driver.dart';
import 'package:voyage/model/single_trip_response.dart';
import 'package:voyage/model/trip_stats_response.dart';
import 'package:voyage/model/vehicle/nearby_device.dart';
// change your licence key on line 76
void main() {
runApp(const ZenApp());
}
class ZenApp extends StatelessWidget {
const ZenApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Zen App',
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: const Color(0xFF121212),
textTheme: const TextTheme(
bodyMedium: TextStyle(fontFamily: 'monospace', fontSize: 16),
),
),
home: const LoginScreen(),
debugShowCheckedModeBanner: false,
);
}
}
/* --------------------- LOGIN SCREEN --------------------- */
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final TextEditingController _name = TextEditingController();
final TextEditingController _email = TextEditingController();
final TextEditingController _phone = TextEditingController();
// create communicator instance once and reuse
final _kruzr = Kruzr360Communicator(
companyName: "Company name provided by kruzr", //Company name provided by kruzr
accountName: "Account name provided by kruzr", // Account name provided by kruzr
);
bool _loading = false;
String _error = '';
Future<void> _requestPermissions() async {
await Permission.locationWhenInUse.request();
await Permission.locationAlways.request();
await Permission.activityRecognition.request();
await Permission.ignoreBatteryOptimizations.request();
await Permission.notification.request();
}
Future<void> _registerUser() async {
setState(() {
_loading = true;
_error = '';
});
await _requestPermissions(); // non-blocking
try {
final initConfig = Kruzr360InitConfig(
licenseKey: "your licence key", // your licence key
appName: "Zen",
notificationChannelId: "zen_trip_channel",
shouldTripAutoStart: true,
shouldTripAutoEnd: true,
allowEventSyncRealTime: true,
);
await Kruzr360Communicator.initializeSDK(initConfig);
final int userId = await _kruzr.registerUserToKruzr(
name: _name.text.trim(),
driverId: _phone.text.trim(),
email: _email.text.trim(),
countryCode: "+91",
phoneNumber: _phone.text.trim(),
);
if (userId > 0) {
// After a successful register, navigate. Check mounted to avoid BuildContext across async gap.
if (!mounted) return;
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) =>
HomeScreen(kruzr: _kruzr, initialUserName: _name.text.trim()),
),
);
} else {
if (!mounted) return;
setState(() {
_error = "User registration failed (no userId returned).";
});
}
} catch (e, st) {
if (!mounted) return;
setState(() {
_error = "Error during registration: $e";
});
debugPrint(st.toString());
} finally {
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(24),
child: ListView(
children: [
const SizedBox(height: 100),
const Text(
'Welcome to Kruzr',
style: TextStyle(fontSize: 32, fontFamily: 'monospace'),
),
const SizedBox(height: 10),
const Text(
'Social Well Being Experiment',
style: TextStyle(fontSize: 16),
),
const SizedBox(height: 30),
TextField(
controller: _name,
decoration: const InputDecoration(labelText: 'Name'),
),
TextField(
controller: _email,
decoration: const InputDecoration(labelText: 'Email'),
),
TextField(
controller: _phone,
decoration: const InputDecoration(labelText: 'Phone Number'),
keyboardType: TextInputType.phone,
),
const SizedBox(height: 30),
if (_error.isNotEmpty)
Text(_error, style: const TextStyle(color: Colors.red)),
ElevatedButton(
onPressed: _loading ? null : _registerUser,
child: Text(_loading ? 'Please wait...' : 'Explore'),
),
],
),
),
);
}
}
/* --------------------- HOME SCREEN --------------------- */
class HomeScreen extends StatefulWidget {
final Kruzr360Communicator kruzr;
final String initialUserName;
const HomeScreen({
super.key,
required this.kruzr,
required this.initialUserName,
});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
RegisteredDriver? _registeredDriver; // overall stats + name
List<SingleTripResponse> _last4Trips = []; // Store last 4 trips
Map<String, TripStatsResponse> _tripStatsMap = {}; // Stats for each trip
final Map<String, dynamic> _tripInsightsMap = {}; // Insights for trips
// ๐ ๏ธ Hardcoded appTripId here as requested
String? _selectedTripId = "6310_1775535987681";
bool _loading = true;
String? _error;
@override
void initState() {
super.initState();
// load after build kicked off
WidgetsBinding.instance.addPostFrameCallback((_) {
_loadAll();
});
}
Future<void> _loadAll() async {
setState(() {
_loading = true;
_error = null;
});
try {
// 1) Try to get registered driver details (registered driver has the totals)
final dynamic driverRaw = await _safeCall(
() => widget.kruzr.userDetails(),
);
_registeredDriver = _parseRegisteredDriver(driverRaw);
// 2) Get latest trips list (plugin provides fetchTripList(offset, limit))
final dynamic tripsRaw = await _safeCall(
() => widget.kruzr.fetchTripList(0, 10),
);
final List<SingleTripResponse>? trips = _parseSingleTripList(tripsRaw);
if (trips != null && trips.isNotEmpty) {
// Get last 4 trips (or less if not enough trips)
_last4Trips = trips.take(4).toList();
// 3) Fetch trip stats for all 4 trips
_tripStatsMap = {};
for (final trip in _last4Trips) {
final appTripId = trip.appTripId;
if (appTripId.isNotEmpty) {
final dynamic tripStatsRaw = await _safeCall(
() => widget.kruzr.fetchTripStatsByAppTripId(appTripId),
);
final stats = _parseTripStats(tripStatsRaw);
if (stats != null) {
_tripStatsMap[appTripId] = stats;
}
}
}
// 4) Fetch insights for all 4 trips
await Future.wait(
_last4Trips.map((trip) async {
final id = trip.appTripId;
if (id.isEmpty) return;
// Optional filter (recommended)
if (trip.tripScoringStatus?.value != "COMPLETED") return;
try {
final insights = await widget.kruzr.fetchTripInsights(id);
_tripInsightsMap[id] = insights;
} catch (e) {
debugPrint("Insights failed for $id: $e");
}
}),
);
}
if (!mounted) return;
setState(() {
_loading = false;
});
} catch (e, st) {
debugPrint("load error: $e\n$st");
if (!mounted) return;
setState(() {
_error = e.toString();
_loading = false;
});
}
}
// run a plugin call and catch exceptions to avoid crashing UI
Future<dynamic> _safeCall(Future<dynamic> Function() fn) async {
try {
return await fn();
} catch (e) {
debugPrint("plugin call failed: $e");
return null;
}
}
// robust parsers: plugin might return Map, JSON-string, or model already
RegisteredDriver? _parseRegisteredDriver(dynamic raw) {
if (raw == null) return null;
try {
if (raw is RegisteredDriver) return raw;
if (raw is String) {
final Map<String, dynamic> m = jsonDecode(raw);
return RegisteredDriver.fromJson(m);
}
if (raw is Map) {
return RegisteredDriver.fromJson(Map<String, dynamic>.from(raw));
}
} catch (e) {
debugPrint("parseRegisteredDriver failed: $e");
}
return null;
}
TripStatsResponse? _parseTripStats(dynamic raw) {
if (raw == null) return null;
try {
if (raw is TripStatsResponse) return raw;
if (raw is String) {
final Map<String, dynamic> m = jsonDecode(raw);
return TripStatsResponse.fromJson(m);
}
if (raw is Map) {
return TripStatsResponse.fromJson(Map<String, dynamic>.from(raw));
}
} catch (e) {
debugPrint("parseTripStats failed: $e");
}
return null;
}
List<SingleTripResponse>? _parseSingleTripList(dynamic raw) {
if (raw == null) return null;
try {
// if it's already a list of SingleTripResponse
if (raw is List<SingleTripResponse>) return raw;
// If plugin returned JSON string array
if (raw is String) {
final decoded = jsonDecode(raw);
if (decoded is List) {
return decoded.map((e) {
if (e is SingleTripResponse) return e;
if (e is Map) {
return SingleTripResponse.fromJson(Map<String, dynamic>.from(e));
}
return SingleTripResponse.fromJson(Map<String, dynamic>.from(e));
}).toList();
}
}
// If plugin returned List<Map>
if (raw is List) {
return raw.map((e) {
if (e is SingleTripResponse) return e;
if (e is Map) {
return SingleTripResponse.fromJson(Map<String, dynamic>.from(e));
}
// fallback: try jsonEncode then parse
return SingleTripResponse.fromJson(
Map<String, dynamic>.from(jsonDecode(e)),
);
}).toList();
}
} catch (e) {
debugPrint("parseSingleTripList failed: $e");
}
return null;
}
// helpers to show safe text
String _asTextNum(num? v, {int fixed = 2}) {
if (v == null) return "-";
return (v.toDouble()).toStringAsFixed(fixed);
}
String _formatDurationFromSeconds(num? seconds) {
if (seconds == null) return "-";
final d = Duration(seconds: seconds.toInt());
String two(int n) => n.toString().padLeft(2, "0");
return "${two(d.inHours)}:${two(d.inMinutes.remainder(60))}:${two(d.inSeconds.remainder(60))}";
}
// Get the currently selected trip
SingleTripResponse? get _selectedTrip {
if (_selectedTripId == null || _last4Trips.isEmpty) return null;
try {
return _last4Trips.firstWhere((t) => t.appTripId == _selectedTripId);
} catch (_) {
return _last4Trips.first;
}
}
// ---------------- DEV TEST HELPERS ----------------
void _logTestResult(String label, dynamic result) {
debugPrint("๐งช [$label] => $result");
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("$label โ"),
duration: const Duration(milliseconds: 700),
),
);
}
Future<void> _runDevTest(String label, Future<dynamic> Function() fn) async {
try {
final res = await fn();
_logTestResult(label, res);
} catch (e, st) {
debugPrint("โ [$label] error: $e\n$st");
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("$label โ $e"), backgroundColor: Colors.red),
);
}
}
// Build a single trip card widget
Widget _buildTripCard(SingleTripResponse trip, int index) {
final stats = _tripStatsMap[trip.appTripId];
final isSelected = trip.appTripId == _selectedTripId;
return GestureDetector(
onTap: () {
setState(() {
_selectedTripId = trip.appTripId;
});
},
child: Card(
color: isSelected ? const Color(0xFF2A2A2A) : const Color(0xFF1E1E1E),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: isSelected
? const BorderSide(color: Colors.blue, width: 2)
: BorderSide.none,
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Trip ${index + 1}",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
if (isSelected)
const Icon(Icons.check_circle, color: Colors.blue, size: 20),
],
),
const SizedBox(height: 8),
Text(
"AppTripId: ${trip.appTripId}",
style: const TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
const SizedBox(height: 4),
Text("Trip start: ${trip.startTime ?? '-'}"),
const SizedBox(height: 6),
Text("Score: ${_asTextNum(trip.overallTripScore, fixed: 2)}"),
Text("Distance: ${_asTextNum(trip.totalDistance)} km"),
Text("Duration: ${trip.getTripDuration() ?? '-'} min"),
Text("Status: ${trip.tripScoringStatus?.value ?? '-'}"),
if (stats != null) ...[
const Divider(),
const Text(
"Stats loaded โ",
style: TextStyle(color: Colors.green, fontSize: 12),
),
],
],
),
),
),
);
}
// UI
@override
Widget build(BuildContext context) {
final displayName = _registeredDriver?.name ?? widget.initialUserName;
return Scaffold(
appBar: AppBar(
title: Text(
displayName,
style: const TextStyle(fontFamily: 'monospace'),
),
backgroundColor: Colors.transparent,
elevation: 0,
),
body: _loading
? const Center(child: CircularProgressIndicator())
: _error != null
? Center(
child: Text(
"Error: $_error",
style: const TextStyle(color: Colors.red),
),
)
: Padding(
padding: const EdgeInsets.all(16),
child: ListView(
children: [
// RegisteredDriver card with overall stats
Card(
color: const Color(0xFF1E1E1E),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Trips taken: ${_registeredDriver?.totalTripCount ?? 0}",
),
Text(
"Total distance: ${_asTextNum(_registeredDriver?.totalDistanceTravelled)} km",
),
Text(
"Total duration: ${_formatDurationFromSeconds(_registeredDriver?.totalTripDurationInSeconds)}",
),
const SizedBox(height: 12),
Text(
"Driving score: ${_asTextNum(_registeredDriver?.averageTripScore, fixed: 2)}",
),
],
),
),
),
const SizedBox(height: 16),
// Last 4 trips section
if (_last4Trips.isNotEmpty) ...[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Last 4 Trips',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Text(
'Tap to select for testing',
style: TextStyle(fontSize: 12, color: Colors.grey[400]),
),
],
),
const SizedBox(height: 8),
// Display all 4 trip cards
...List.generate(
_last4Trips.length,
(index) => Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildTripCard(_last4Trips[index], index),
),
),
] else
const Text("No recent trips found in local DB"),
// Hamesha show selected trip info (taaki hardcoded wali clearly dikhe)
if (_selectedTripId != null) ...[
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.blue.withOpacity(0.3)),
),
child: Row(
children: [
const Icon(Icons.info_outline, color: Colors.blue, size: 18),
const SizedBox(width: 8),
Expanded(
child: Text(
"Selected for testing: $_selectedTripId",
style: const TextStyle(fontSize: 12, color: Colors.blue),
overflow: TextOverflow.ellipsis,
),
),
],
),
),
],
const SizedBox(height: 24),
ElevatedButton(
onPressed: () async {
// ensure permissions before starting
final granted = await [
Permission.location,
Permission.locationAlways,
Permission.activityRecognition,
Permission.ignoreBatteryOptimizations,
].request();
if (!granted.values.every((s) => s.isGranted)) {
// ignore: use_build_context_synchronously
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Please grant required permissions"),
),
);
return;
}
try {
final started = await widget.kruzr.startTrip();
debugPrint("Trip started: $started");
// reload latest trip after a short delay if needed
await Future.delayed(const Duration(seconds: 1));
_loadAll();
} catch (e) {
debugPrint("startTrip error: $e");
}
},
child: const Text("Start Trip"),
),
ElevatedButton(
onPressed: () async {
try {
final stopped = await widget.kruzr.stopTrip();
debugPrint("Trip stopped: $stopped");
// refresh views
await Future.delayed(const Duration(milliseconds: 800));
_loadAll();
} catch (e) {
debugPrint("stopTrip error: $e");
}
},
child: const Text("Stop Trip"),
),
const SizedBox(height: 32),
const Divider(),
const Text(
"Developer Test Panel",
style: TextStyle(fontSize: 18, fontFamily: 'monospace'),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () => _runDevTest(
"userDetails",
() => widget.kruzr.userDetails(),
),
child: const Text("Test: userDetails"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getUserRank",
() => widget.kruzr.getCurrentUserRank(),
),
child: const Text("Test: getUserRank"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getLeaderboardTop10",
() => widget.kruzr.getLeaderboardTop10(),
),
child: const Text("Test: getLeaderboardTop10"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"fetchMyAchievements",
() => widget.kruzr.fetchMyAchievements(),
),
child: const Text("Test: fetchMyAchievements"),
),
ElevatedButton(
onPressed: _selectedTripId == null
? null
: () => _runDevTest(
"fetchRoute (GeoJSON)",
() => widget.kruzr.fetchRoute(_selectedTripId!),
),
child: const Text("Test: fetchRoute"),
),
ElevatedButton(
onPressed: _selectedTripId == null
? null
: () => _runDevTest(
"getPossibleInterventions",
() => widget.kruzr
.getPossibleInterventionsForAppTripId(
_selectedTripId!,
),
),
child: const Text("Test: getPossibleInterventions"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"scanForNearbyDevices",
() => widget.kruzr.scanForNearbyDevices(),
),
child: const Text("Test: scanForNearbyDevices"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"stopScanningForNearbyDevices",
() => widget.kruzr.stopScanningForNearbyDevices(),
),
child: const Text("Test: stopScanning"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getAllPairedDevices",
() => widget.kruzr.getAllPairedDevices(),
),
child: const Text("Test: getAllPairedDevices"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getConnectedDevices",
() => widget.kruzr.getConnectedDevices(),
),
child: const Text("Test: getConnectedDevices"),
),
ElevatedButton(
onPressed: () => _runDevTest("saveVehicle", () {
final device = NearbyDevice(
id: "DEV_TEST_VEHICLE",
name: "Test Car",
vehicleId: "TEST_VEHICLE_123",
);
widget.kruzr.saveVehicle(device); // void method
return Future.value("OK"); // wrap in Future
}),
child: const Text("Test: saveVehicle"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getAllSavedVehicles",
() => widget.kruzr.getAllSavedVehicles(),
),
child: const Text("Test: getAllSavedVehicles"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getUserStreak",
() => widget.kruzr.getUserStreak(),
),
child: const Text("Test: getUserStreak"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"removeAllSavedVehicles",
() async => widget.kruzr.removeAllSavedVehicles(),
),
child: const Text("Test: removeAllSavedVehicles"),
),
ElevatedButton(
onPressed: () => _runDevTest("removeSavedVehicle", () {
final device = NearbyDevice(
id: "DEV_TEST_VEHICLE",
name: "Test Car",
vehicleId: "TEST_VEHICLE_123",
);
widget.kruzr.removeSavedVehicle(device); // void call
return Future.value("OK");
}),
child: const Text("Test: removeSavedVehicle"),
),
ElevatedButton(
onPressed: () => _runDevTest("editSavedVehicle", () {
final device = NearbyDevice(
id: "EDIT_TEST_MAC",
name: "Edited Car",
vehicleId: null,
);
widget.kruzr.editSavedVehicle(device); // void
return Future.value("OK");
}),
child: const Text("Test: editSavedVehicle"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getCurrentTripData",
() => widget.kruzr.getCurrentTripData(),
),
child: const Text("Test: getCurrentTripData"),
),
ElevatedButton(
onPressed: _selectedTripId == null
? null
: () => _runDevTest(
"fetchTripStatsByAppTripId",
() => widget.kruzr
.fetchTripStatsByAppTripId(_selectedTripId!),
),
child: const Text("Test: fetchTripStatsByAppTripId"),
),
ElevatedButton(
onPressed: _selectedTripId == null
? null
: () => _runDevTest(
"fetchTripDetailsByAppTripId",
() => widget.kruzr
.fetchTripDetailsByAppTripId(_selectedTripId!),
),
child: const Text("Test: fetchTripDetailsByAppTripId"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"fetchAvailableRewards",
() => widget.kruzr.fetchAvailableRewards(),
),
child: const Text("Test: fetchAvailableRewards"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"fetchEarnedRewards",
() => widget.kruzr.fetchEarnedRewards(),
),
child: const Text("Test: fetchEarnedRewards"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"fetchUserProfileTierRequirements",
() => widget.kruzr.fetchUserProfileTierRequirements(),
),
child: const Text("Test: fetchUserProfileTierRequirements"),
),
const SizedBox(height: 24),
const Divider(),
const Text(
"Auto Trip / Sync Controls",
style: TextStyle(fontSize: 18, fontFamily: 'monospace'),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () => _runDevTest(
"isTripAutoStartEnabled",
() => widget.kruzr.getTripAutoStartEnabled(),
),
child: const Text("Test: isTripAutoStartEnabled"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"isTripAutoEndEnabled",
() => widget.kruzr.getTripAutoEndEnabled(),
),
child: const Text("Test: isTripAutoEndEnabled"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"Enable Auto Trip Start",
() => widget.kruzr.setTripAutoStartEnabled(true),
),
child: const Text("Enable Auto Trip Start"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"Disable Auto Trip Start",
() => widget.kruzr.setTripAutoStartEnabled(false),
),
child: const Text("Disable Auto Trip Start"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"Enable Auto Trip End",
() => widget.kruzr.setTripAutoEndEnabled(true),
),
child: const Text("Enable Auto Trip End"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"Disable Auto Trip End",
() => widget.kruzr.setTripAutoEndEnabled(false),
),
child: const Text("Disable Auto Trip End"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"isEventSyncRealTimeEnabled",
() => widget.kruzr.isEventSyncRealTimeEnabled(),
),
child: const Text("Test: isEventSyncRealTimeEnabled"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"Enable RealTime Event Sync",
() => widget.kruzr.shouldEventSyncRealTime(true),
),
child: const Text("Enable RealTime Event Sync"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"Enable shouldAutoStartOnlyIfVehicleConnected",
() => widget.kruzr.setAutoTripStartOnlyIfVehicleConnected(true),
),
child: const Text("Enable shouldAutoStartOnlyIfVehicleConnected"),
),
ElevatedButton(
onPressed: () => _runDevTest(
"getAutoTripStartOnlyIfVehicleConnected",
() => widget.kruzr.getAutoTripStartOnlyIfVehicleConnected(),
),
child: const Text("Test: getAutoTripStartOnlyIfVehicleConnected"),
),
ElevatedButton(
onPressed: _selectedTripId == null
? null
: () => _runDevTest(
"fetchTripInsights (Selected)",
() => widget.kruzr.fetchTripInsights(_selectedTripId!),
),
child: const Text("Test: fetchTripInsights"),
),
ElevatedButton(
onPressed: _selectedTripId == null
? null
: () => _runDevTest(
"fetchTripInsights ",
() async {
if (_last4Trips.isEmpty) {
final res = await widget.kruzr.fetchTripInsights(_selectedTripId!);
debugPrint("Insights for $_selectedTripId => $res");
return "Done for Hardcoded ID";
}
else {
for (final trip in _last4Trips) {
final id = trip.appTripId;
if (id.isEmpty) continue;
final res = await widget.kruzr.fetchTripInsights(id);
debugPrint("Insights for $id => $res");
}
return "Done for ${_last4Trips.length} trips";
}
},
),
child: const Text("Test: fetchTripInsights (ALL 4)"),
),
],
),
),
);
}
}