auto-claude/001-normalize-code-update-packages-widgetify-component #1
@ -146,5 +146,8 @@
|
||||
}
|
||||
},
|
||||
"serverError": "Server error - Please contact support",
|
||||
"retake": "Retake"
|
||||
"retake": "Retake",
|
||||
"completingDelivery": "Completing delivery...",
|
||||
"markingAsUncompleted": "Marking as uncompleted...",
|
||||
"deliveryMarkedUncompleted": "Delivery marked as uncompleted"
|
||||
}
|
||||
|
||||
@ -146,5 +146,8 @@
|
||||
}
|
||||
},
|
||||
"serverError": "Erreur serveur - Veuillez contacter le support",
|
||||
"retake": "Reprendre"
|
||||
"retake": "Reprendre",
|
||||
"completingDelivery": "Completion de la livraison...",
|
||||
"markingAsUncompleted": "Marquage comme a livrer...",
|
||||
"deliveryMarkedUncompleted": "Livraison marquee comme a livrer"
|
||||
}
|
||||
|
||||
@ -631,6 +631,24 @@ abstract class AppLocalizations {
|
||||
/// In en, this message translates to:
|
||||
/// **'Retake'**
|
||||
String get retake;
|
||||
|
||||
/// No description provided for @completingDelivery.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Completing delivery...'**
|
||||
String get completingDelivery;
|
||||
|
||||
/// No description provided for @markingAsUncompleted.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Marking as uncompleted...'**
|
||||
String get markingAsUncompleted;
|
||||
|
||||
/// No description provided for @deliveryMarkedUncompleted.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Delivery marked as uncompleted'**
|
||||
String get deliveryMarkedUncompleted;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
||||
@ -302,4 +302,13 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get retake => 'Retake';
|
||||
|
||||
@override
|
||||
String get completingDelivery => 'Completing delivery...';
|
||||
|
||||
@override
|
||||
String get markingAsUncompleted => 'Marking as uncompleted...';
|
||||
|
||||
@override
|
||||
String get deliveryMarkedUncompleted => 'Delivery marked as uncompleted';
|
||||
}
|
||||
|
||||
@ -302,4 +302,13 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get retake => 'Reprendre';
|
||||
|
||||
@override
|
||||
String get completingDelivery => 'Completion de la livraison...';
|
||||
|
||||
@override
|
||||
String get markingAsUncompleted => 'Marquage comme a livrer...';
|
||||
|
||||
@override
|
||||
String get deliveryMarkedUncompleted => 'Livraison marquee comme a livrer';
|
||||
}
|
||||
|
||||
@ -11,10 +11,12 @@ import '../providers/providers.dart';
|
||||
import '../api/client.dart';
|
||||
import '../utils/toast_helper.dart';
|
||||
import '../api/openapi_config.dart';
|
||||
import '../utils/breakpoints.dart';
|
||||
import '../utils/http_client_factory.dart';
|
||||
import '../components/collapsible_routes_sidebar.dart';
|
||||
import '../components/dark_mode_map.dart';
|
||||
import '../components/loading_dialog.dart';
|
||||
import '../components/notes_dialog.dart';
|
||||
import '../components/photo_capture_dialog.dart';
|
||||
import '../services/location_permission_service.dart';
|
||||
import 'deliveries_page.dart';
|
||||
import 'settings_page.dart';
|
||||
@ -81,13 +83,14 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
Delivery delivery,
|
||||
int routeFragmentId,
|
||||
) async {
|
||||
// Capture l10n before async operations to avoid BuildContext across async gaps
|
||||
final l10n = AppLocalizations.of(context);
|
||||
final authService = ref.read(authServiceProvider);
|
||||
|
||||
// Ensure we have a valid token (automatically refreshes if needed)
|
||||
final token = await authService.ensureValidToken();
|
||||
if (token == null) {
|
||||
if (mounted) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
ToastHelper.showError(context, l10n.authenticationRequired);
|
||||
}
|
||||
return;
|
||||
@ -102,27 +105,7 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
switch (action) {
|
||||
case 'complete':
|
||||
if (mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return const Center(
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text('Completing delivery...'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
LoadingDialog.show(context, message: l10n.completingDelivery);
|
||||
}
|
||||
|
||||
final result = await authClient.executeCommand(
|
||||
@ -134,7 +117,7 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
result.when(
|
||||
success: (_) async {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
LoadingDialog.hide(context);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
@ -176,23 +159,21 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
ToastHelper.showSuccess(context, l10n.deliverySuccessful);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (error) {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
LoadingDialog.hide(context);
|
||||
}
|
||||
|
||||
debugPrint('Complete delivery failed - Type: ${error.type}, Message: ${error.message}');
|
||||
debugPrint('Error details: ${error.details}');
|
||||
if (mounted) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
String errorMessage = l10n.error(error.message);
|
||||
if (error.statusCode == 500) {
|
||||
errorMessage = 'Server error - Please contact support';
|
||||
errorMessage = l10n.serverError;
|
||||
}
|
||||
ToastHelper.showError(context, errorMessage);
|
||||
}
|
||||
@ -202,37 +183,17 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
|
||||
case 'uncomplete':
|
||||
if (mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return const Center(
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text('Marking as uncompleted...'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
LoadingDialog.show(context, message: l10n.markingAsUncompleted);
|
||||
}
|
||||
|
||||
final result = await authClient.executeCommand(
|
||||
final uncompleteResult = await authClient.executeCommand(
|
||||
endpoint: 'markDeliveryAsUncompleted',
|
||||
command: MarkDeliveryAsUncompletedCommand(deliveryId: delivery.id),
|
||||
);
|
||||
result.when(
|
||||
uncompleteResult.when(
|
||||
success: (_) async {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
LoadingDialog.hide(context);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
@ -257,18 +218,16 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
ToastHelper.showSuccess(context, 'Delivery marked as uncompleted');
|
||||
ToastHelper.showSuccess(context, l10n.deliveryMarkedUncompleted);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (error) {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
LoadingDialog.hide(context);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
ToastHelper.showError(context, l10n.error(error.message));
|
||||
}
|
||||
},
|
||||
@ -289,12 +248,12 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
Delivery delivery,
|
||||
) async {
|
||||
final authService = ref.read(authServiceProvider);
|
||||
final l10n = AppLocalizations.of(context);
|
||||
|
||||
// Ensure we have a valid token (automatically refreshes if needed)
|
||||
final token = await authService.ensureValidToken();
|
||||
if (token == null) {
|
||||
if (mounted) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
ToastHelper.showError(context, l10n.authenticationRequired);
|
||||
}
|
||||
return;
|
||||
@ -309,7 +268,7 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
);
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ToastHelper.showError(context, 'Camera error: $e');
|
||||
ToastHelper.showError(context, l10n.cameraError(e.toString()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -320,45 +279,11 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
final bool? confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return AlertDialog(
|
||||
title: const Text('Confirm Photo'),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(dialogContext).size.height * 0.5,
|
||||
maxWidth: MediaQuery.of(dialogContext).size.width * 0.8,
|
||||
),
|
||||
child: Image.file(
|
||||
File(pickedFile!.path),
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Upload this photo for ${delivery.name}?',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(false),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(true),
|
||||
child: const Text('Upload'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
// Show photo confirmation dialog
|
||||
final bool? confirmed = await PhotoCaptureDialog.show(
|
||||
context,
|
||||
imageFile: File(pickedFile.path),
|
||||
deliveryName: delivery.name,
|
||||
);
|
||||
|
||||
if (confirmed != true) {
|
||||
@ -367,27 +292,8 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return const Center(
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text('Uploading photo...'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
// Show uploading dialog
|
||||
LoadingDialog.show(context, message: l10n.uploadingPhoto);
|
||||
|
||||
try {
|
||||
final Uri uploadUrl = Uri.parse(
|
||||
@ -408,33 +314,31 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
client.close();
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
LoadingDialog.hide(context);
|
||||
}
|
||||
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
if (mounted) {
|
||||
ToastHelper.showSuccess(context, 'Photo uploaded successfully');
|
||||
ToastHelper.showSuccess(context, l10n.photoUploadSuccess);
|
||||
}
|
||||
ref.refresh(allDeliveriesProvider);
|
||||
ref.invalidate(allDeliveriesProvider);
|
||||
} else {
|
||||
debugPrint('Photo upload failed - Status: ${response.statusCode}');
|
||||
debugPrint('Response body: ${response.body}');
|
||||
if (mounted) {
|
||||
String errorMessage = 'Upload failed';
|
||||
String errorMessage = l10n.photoUploadFailed(response.statusCode);
|
||||
if (response.statusCode == 500) {
|
||||
errorMessage = 'Server error - Please contact support';
|
||||
errorMessage = l10n.serverError;
|
||||
} else if (response.statusCode == 401) {
|
||||
errorMessage = 'Authentication required - Please log in again';
|
||||
} else {
|
||||
errorMessage = 'Upload failed: ${response.statusCode}';
|
||||
errorMessage = l10n.authenticationRequired;
|
||||
}
|
||||
ToastHelper.showError(context, errorMessage);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
ToastHelper.showError(context, 'Upload error: $e');
|
||||
LoadingDialog.hide(context);
|
||||
ToastHelper.showError(context, l10n.uploadError(e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -462,53 +366,14 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
}
|
||||
|
||||
Future<void> _showNotesDialog(Delivery delivery) async {
|
||||
final notes = delivery.orders
|
||||
.where((order) => order.note != null && order.note!.isNotEmpty)
|
||||
.map((order) => order.note!)
|
||||
.toList();
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
if (notes.isEmpty) {
|
||||
ToastHelper.showInfo(context, 'No notes attached to this delivery');
|
||||
return;
|
||||
}
|
||||
final l10n = AppLocalizations.of(context);
|
||||
final hasNotes = await NotesDialog.show(context, delivery);
|
||||
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return AlertDialog(
|
||||
title: Text('Notes for ${delivery.name}'),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: notes.map((note) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16.0),
|
||||
child: Text(
|
||||
note,
|
||||
style: Theme.of(dialogContext).textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
)).toList(),
|
||||
),
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
actionsPadding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||
actions: [
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(),
|
||||
child: const Text('Close'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
if (!hasNotes && mounted) {
|
||||
ToastHelper.showInfo(context, l10n.noNotesMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -516,7 +381,7 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
final routesData = ref.watch(deliveryRoutesProvider);
|
||||
final allDeliveriesData = ref.watch(allDeliveriesProvider);
|
||||
final userProfile = ref.watch(userProfileProvider);
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final l10n = AppLocalizations.of(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@ -535,8 +400,8 @@ class _RoutesPageState extends ConsumerState<RoutesPage> {
|
||||
onPressed: (routesData.isLoading || allDeliveriesData.isLoading)
|
||||
? null
|
||||
: () {
|
||||
ref.refresh(deliveryRoutesProvider);
|
||||
ref.refresh(allDeliveriesProvider);
|
||||
ref.invalidate(deliveryRoutesProvider);
|
||||
ref.invalidate(allDeliveriesProvider);
|
||||
},
|
||||
tooltip: 'Refresh',
|
||||
),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user