From 924367c70e8b9cafdb97c3adf53b15bc12438b22 Mon Sep 17 00:00:00 2001 From: John Mizerek Date: Wed, 7 Jan 2026 11:46:13 -0800 Subject: [PATCH] Improve snackbar styling and fix business switching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Snackbar Improvements: - All snackbars now have colored backgrounds (green/red/orange/blue) - Added icons to snackbar messages (check_circle, error, warning, info) - Floating behavior with bottom margin to avoid obscuring action buttons - Consistent styling across menu_browse, cart_view, and login screens App State Fixes: - Clear cartItemCount when switching businesses (setBusiness, setServicePoint, setBusinessAndServicePoint, clearAll) - Prevents stale cart count showing after switching restaurants 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 +- .../AppIcon.appiconset/Contents.json | 123 +----------------- lib/app/app_state.dart | 4 + lib/screens/cart_view_screen.dart | 45 ++++++- lib/screens/login_screen.dart | 13 +- lib/screens/menu_browse_screen.dart | 39 +++++- pubspec.lock | 4 +- pubspec.yaml | 2 +- 8 files changed, 99 insertions(+), 137 deletions(-) diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 5f349f7..900973f 100644 --- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,9 @@ - + + + diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index 5361129..d0d98aa 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1 @@ -{ - "images" : [ - { - "filename" : "Icon-App-20x20@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "Icon-App-20x20@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "Icon-App-29x29@1x.png", - "idiom" : "iphone", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "Icon-App-29x29@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "Icon-App-29x29@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "Icon-App-40x40@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "Icon-App-40x40@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "Icon-App-60x60@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "Icon-App-60x60@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "Icon-App-20x20@1x.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "Icon-App-20x20@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "Icon-App-29x29@1x.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "Icon-App-29x29@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "Icon-App-40x40@1x.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "Icon-App-40x40@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "Icon-App-76x76@1x.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "Icon-App-76x76@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "Icon-App-83.5x83.5@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "Icon-App-1024x1024@1x.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} +{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/lib/app/app_state.dart b/lib/app/app_state.dart index 6cf3392..731d20b 100644 --- a/lib/app/app_state.dart +++ b/lib/app/app_state.dart @@ -40,6 +40,7 @@ class AppState extends ChangeNotifier { _cartOrderId = null; _cartOrderUuid = null; + _cartItemCount = 0; notifyListeners(); } @@ -49,6 +50,7 @@ class AppState extends ChangeNotifier { _cartOrderId = null; _cartOrderUuid = null; + _cartItemCount = 0; notifyListeners(); } @@ -66,6 +68,7 @@ class AppState extends ChangeNotifier { _cartOrderId = null; _cartOrderUuid = null; + _cartItemCount = 0; notifyListeners(); } @@ -122,6 +125,7 @@ class AppState extends ChangeNotifier { _cartOrderId = null; _cartOrderUuid = null; + _cartItemCount = 0; _activeOrderId = null; _activeOrderStatusId = null; diff --git a/lib/screens/cart_view_screen.dart b/lib/screens/cart_view_screen.dart index cc2b51d..311535f 100644 --- a/lib/screens/cart_view_screen.dart +++ b/lib/screens/cart_view_screen.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../app/app_state.dart'; @@ -204,8 +204,16 @@ class _CartViewScreenState extends State { if (paymentResult.error != 'Payment cancelled') { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text(paymentResult.error ?? 'Payment failed'), + content: Row( + children: [ + Icon(Icons.error, color: Colors.white), + SizedBox(width: 8), + Expanded(child: Text(paymentResult.error ?? 'Payment failed')), + ], + ), backgroundColor: Colors.red, + behavior: SnackBarBehavior.floating, + margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); } @@ -230,10 +238,17 @@ class _CartViewScreenState extends State { // This works even after the cart screen is popped rootScaffoldMessengerKey.currentState?.showSnackBar( SnackBar( - content: Text(update.message), + content: Row( + children: [ + Icon(Icons.notifications_active, color: Colors.white), + SizedBox(width: 8), + Expanded(child: Text(update.message)), + ], + ), backgroundColor: _getStatusColorStatic(update.statusId), duration: const Duration(seconds: 5), behavior: SnackBarBehavior.floating, + margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); }, @@ -247,11 +262,21 @@ class _CartViewScreenState extends State { // Show success message ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - "Payment successful! Order placed. You'll receive notifications as your order is prepared.", + content: const Row( + children: [ + Icon(Icons.check_circle, color: Colors.white), + SizedBox(width: 8), + Expanded( + child: Text( + "Payment successful! Order placed. You'll receive notifications as your order is prepared.", + ), + ), + ], ), backgroundColor: Colors.green, duration: const Duration(seconds: 5), + behavior: SnackBarBehavior.floating, + margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); @@ -263,8 +288,16 @@ class _CartViewScreenState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('Error: ${e.toString()}'), + content: Row( + children: [ + const Icon(Icons.error, color: Colors.white), + const SizedBox(width: 8), + Expanded(child: Text('Error: ${e.toString()}')), + ], + ), backgroundColor: Colors.red, + behavior: SnackBarBehavior.floating, + margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); } diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart index 0e3441a..5da2cd8 100644 --- a/lib/screens/login_screen.dart +++ b/lib/screens/login_screen.dart @@ -1,4 +1,4 @@ -import "package:flutter/material.dart"; +import "package:flutter/material.dart"; import "package:provider/provider.dart"; import "../app/app_router.dart"; @@ -185,7 +185,16 @@ class _LoginScreenState extends State { onPressed: _isLoading ? null : () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( - content: Text("Registration not yet implemented"), + content: Row( + children: [ + Icon(Icons.info, color: Colors.white), + SizedBox(width: 8), + Text("Registration not yet implemented"), + ], + ), + backgroundColor: Colors.blue, + behavior: SnackBarBehavior.floating, + margin: EdgeInsets.only(bottom: 80, left: 16, right: 16), ), ); }, diff --git a/lib/screens/menu_browse_screen.dart b/lib/screens/menu_browse_screen.dart index fa09ba1..79f7ad3 100644 --- a/lib/screens/menu_browse_screen.dart +++ b/lib/screens/menu_browse_screen.dart @@ -736,7 +736,18 @@ class _MenuBrowseScreenState extends State { if (_businessId == null || _servicePointId == null) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("Missing required information")), + const SnackBar( + content: Row( + children: [ + Icon(Icons.warning, color: Colors.white), + SizedBox(width: 8), + Text("Missing required information"), + ], + ), + backgroundColor: Colors.orange, + behavior: SnackBarBehavior.floating, + margin: EdgeInsets.only(bottom: 80, left: 16, right: 16), + ), ); return; } @@ -808,13 +819,35 @@ class _MenuBrowseScreenState extends State { : "Added ${item.name} with ${selectedModifierIds.length} customizations (${cart.itemCount} item${cart.itemCount == 1 ? '' : 's'})"; ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message)), + SnackBar( + content: Row( + children: [ + const Icon(Icons.check_circle, color: Colors.white), + const SizedBox(width: 8), + Expanded(child: Text(message)), + ], + ), + backgroundColor: Colors.green, + behavior: SnackBarBehavior.floating, + margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), + ), ); } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Error adding to cart: $e")), + SnackBar( + content: Row( + children: [ + const Icon(Icons.error, color: Colors.white), + const SizedBox(width: 8), + Expanded(child: Text("Error adding to cart: $e")), + ], + ), + backgroundColor: Colors.red, + behavior: SnackBarBehavior.floating, + margin: const EdgeInsets.only(bottom: 80, left: 16, right: 16), + ), ); } } diff --git a/pubspec.lock b/pubspec.lock index 34d257d..8e738ac 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -122,10 +122,10 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" url: "https://pub.dev" source: hosted - version: "0.13.1" + version: "0.14.4" flutter_lints: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index f184b5b..893a235 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,7 +21,7 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^4.0.0 - flutter_launcher_icons: ^0.13.1 + flutter_launcher_icons: ^0.14.4 flutter_launcher_icons: android: true