fix cart, fix log cart

This commit is contained in:
Phuoc Nguyen
2025-12-11 16:39:25 +07:00
parent e3632d4445
commit fc6a4f038e
4 changed files with 65 additions and 44 deletions

View File

@@ -79,7 +79,8 @@ class SentryService {
..beforeSend = (event, hint) {
// Filter out certain errors if needed
// Return null to drop the event
return event;
// return event;
return null;
};
},
appRunner: appRunner,

View File

@@ -36,6 +36,7 @@ class CartPage extends ConsumerStatefulWidget {
class _CartPageState extends ConsumerState<CartPage> {
bool _isSyncing = false;
bool _hasLoggedViewCart = false;
// Cart is initialized once in home_page.dart at app startup
// Provider has keepAlive: true, so no need to reload here
@@ -44,20 +45,12 @@ class _CartPageState extends ConsumerState<CartPage> {
// and in checkout button handler for checkout flow.
// No dispose() method needed - using ref.read() in dispose() is unsafe.
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final cartState = ref.watch(cartProvider);
void _logViewCartOnce(CartState cartState) {
if (_hasLoggedViewCart || cartState.isEmpty) return;
_hasLoggedViewCart = true;
final itemCount = cartState.itemCount;
final hasSelection = cartState.selectedCount > 0;
// Log view cart analytics event when cart has items
if (cartState.isNotEmpty) {
AnalyticsService.logViewCart(
cartValue: cartState.selectedTotal,
cartValue: cartState.totalPrice,
items: cartState.items.map((item) => AnalyticsEventItem(
itemId: item.product.productId,
itemName: item.product.name,
@@ -67,6 +60,17 @@ class _CartPageState extends ConsumerState<CartPage> {
);
}
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final cartState = ref.watch(cartProvider);
// Log view cart analytics event only once when page opens
_logViewCartOnce(cartState);
final itemCount = cartState.itemCount;
final hasSelection = cartState.selectedCount > 0;
return PopScope(
// Intercept back navigation to sync pending updates
onPopInvokedWithResult: (didPop, result) async {
@@ -346,6 +350,7 @@ class _CartPageState extends ConsumerState<CartPage> {
/// Build error banner (shown at top when there's an error but cart has items)
Widget _buildErrorBanner(String errorMessage) {
print(errorMessage);
return Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),

View File

@@ -7,7 +7,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart';
import 'package:go_router/go_router.dart';
import 'package:worker/core/utils/extensions.dart';
import 'package:worker/core/widgets/loading_indicator.dart';
import 'package:worker/core/theme/typography.dart';
@@ -113,8 +113,13 @@ class _CartItemWidgetState extends ConsumerState<CartItemWidget> {
const SizedBox(width: 12),
// Product Image (bigger: 100x100)
ClipRRect(
// Product Image (bigger: 100x100) - tap to navigate to product detail
GestureDetector(
onTap: () {
// Navigate to product detail with product ID in path
context.push('/products/${widget.item.product.productId}');
},
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CachedNetworkImage(
imageUrl: widget.item.product.thumbnail.isNotEmpty
@@ -145,6 +150,7 @@ class _CartItemWidgetState extends ConsumerState<CartItemWidget> {
),
),
),
),
const SizedBox(width: 12),
@@ -193,14 +199,15 @@ class _CartItemWidgetState extends ConsumerState<CartItemWidget> {
const SizedBox(width: 8),
// Quantity TextField
// Quantity TextField - uses text keyboard for Done button on iOS/Android
SizedBox(
width: 50,
height: 32,
child: TextField(
controller: _quantityController,
focusNode: _quantityFocusNode,
keyboardType: TextInputType.number,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
textAlign: TextAlign.center,
style: AppTypography.titleMedium.copyWith(
fontWeight: FontWeight.w600,

View File

@@ -138,7 +138,15 @@ class ProductsRemoteDataSource {
throw Exception('Product not found: $itemCode');
}
return ProductModel.fromJson(message as Map<String, dynamic>);
// Handle API error response: {success: false, message: "Item not found"}
if (message is Map<String, dynamic>) {
if (message['success'] == false) {
throw Exception(message['message'] ?? 'Product not found: $itemCode');
}
return ProductModel.fromJson(message);
}
throw Exception('Invalid response format for product: $itemCode');
} on DioException catch (e) {
if (e.response?.statusCode == 404) {
throw Exception('Product not found: $itemCode');