Clean up debug code and unused files
- Removed all debug print statements from menu_browse_screen.dart - Removed all debug print statements from api.dart - Deleted unused beacon_scan_screen_broken.dart backup file - Kept debugPrint statements in beacon_scan_screen.dart and beacon_permissions.dart for debugging beacon issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
0a8c12c1d3
commit
114401c130
3 changed files with 0 additions and 304 deletions
|
|
@ -1,243 +0,0 @@
|
||||||
import 'dart:async';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:beacons_plugin/beacons_plugin.dart';
|
|
||||||
|
|
||||||
import '../app/app_router.dart';
|
|
||||||
import '../app/app_state.dart';
|
|
||||||
import '../services/beacon_permissions.dart';
|
|
||||||
import '../services/api.dart';
|
|
||||||
|
|
||||||
class BeaconScanScreen extends StatefulWidget {
|
|
||||||
const BeaconScanScreen({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<BeaconScanScreen> createState() => _BeaconScanScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BeaconScanScreenState extends State<BeaconScanScreen> {
|
|
||||||
String _status = 'Initializing...';
|
|
||||||
bool _scanning = false;
|
|
||||||
bool _permissionsGranted = false;
|
|
||||||
|
|
||||||
// Track beacons by UUID -> (BeaconID, RSSI)
|
|
||||||
final Map<String, MapEntry<int, int>> _detectedBeacons = {};
|
|
||||||
Map<String, int> _uuidToBeaconId = {};
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_startScanFlow();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _startScanFlow() async {
|
|
||||||
// Step 1: Request permissions
|
|
||||||
setState(() => _status = 'Requesting permissions...');
|
|
||||||
|
|
||||||
final granted = await BeaconPermissions.requestPermissions();
|
|
||||||
|
|
||||||
if (!granted) {
|
|
||||||
setState(() {
|
|
||||||
_status = 'Permissions denied';
|
|
||||||
_permissionsGranted = false;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() => _permissionsGranted = true);
|
|
||||||
|
|
||||||
// Step 2: Fetch all active beacons from server
|
|
||||||
setState(() => _status = 'Loading beacon data...');
|
|
||||||
|
|
||||||
try {
|
|
||||||
_uuidToBeaconId = await Api.listAllBeacons();
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('[BeaconScan] Error loading beacons: $e');
|
|
||||||
_uuidToBeaconId = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_uuidToBeaconId.isEmpty) {
|
|
||||||
// No beacons in database, skip scan and go straight to manual selection
|
|
||||||
debugPrint('[BeaconScan] No beacons in database, going to restaurant select');
|
|
||||||
if (mounted) _navigateToRestaurantSelect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: Perform initial scan
|
|
||||||
setState(() {
|
|
||||||
_status = 'Scanning for nearby beacons...';
|
|
||||||
_scanning = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
await _performInitialScan();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _performInitialScan() async {
|
|
||||||
try {
|
|
||||||
// Setup beacon monitoring
|
|
||||||
await BeaconsPlugin.listenToBeacons(
|
|
||||||
_beaconDataReceived,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Start beacon monitoring
|
|
||||||
await BeaconsPlugin.addRegion(
|
|
||||||
"PayfritBeacons",
|
|
||||||
"00000000-0000-0000-0000-000000000000", // Placeholder UUID
|
|
||||||
);
|
|
||||||
|
|
||||||
await BeaconsPlugin.startMonitoring();
|
|
||||||
|
|
||||||
// Scan for 3 seconds
|
|
||||||
await Future.delayed(const Duration(seconds: 3));
|
|
||||||
|
|
||||||
// Stop scanning
|
|
||||||
await BeaconsPlugin.stopMonitoring();
|
|
||||||
|
|
||||||
if (!mounted) return;
|
|
||||||
|
|
||||||
if (_detectedBeacons.isEmpty) {
|
|
||||||
// No beacons found
|
|
||||||
setState(() => _status = 'No beacons nearby');
|
|
||||||
await Future.delayed(const Duration(milliseconds: 800));
|
|
||||||
if (mounted) _navigateToRestaurantSelect();
|
|
||||||
} else {
|
|
||||||
// Find beacon with highest RSSI
|
|
||||||
final best = _findBestBeacon();
|
|
||||||
if (best != null) {
|
|
||||||
setState(() => _status = 'Beacon detected! Loading menu...');
|
|
||||||
await _autoSelectBusinessFromBeacon(best);
|
|
||||||
} else {
|
|
||||||
_navigateToRestaurantSelect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('[BeaconScan] Error during scan: $e');
|
|
||||||
if (mounted) {
|
|
||||||
setState(() => _status = 'Scan error: ${e.toString()}');
|
|
||||||
await Future.delayed(const Duration(seconds: 2));
|
|
||||||
if (mounted) _navigateToRestaurantSelect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _beaconDataReceived(dynamic result) {
|
|
||||||
if (result is Map) {
|
|
||||||
try {
|
|
||||||
final uuid = (result["uuid"] ?? "").toString().trim().toUpperCase().replaceAll('-', '');
|
|
||||||
final rssi = int.tryParse((result["rssi"] ?? "-100").toString()) ?? -100;
|
|
||||||
|
|
||||||
if (uuid.isNotEmpty && _uuidToBeaconId.containsKey(uuid)) {
|
|
||||||
final beaconId = _uuidToBeaconId[uuid]!;
|
|
||||||
|
|
||||||
// Update if this is a new beacon or better RSSI
|
|
||||||
if (!_detectedBeacons.containsKey(uuid) || _detectedBeacons[uuid]!.value < rssi) {
|
|
||||||
setState(() {
|
|
||||||
_detectedBeacons[uuid] = MapEntry(beaconId, rssi);
|
|
||||||
});
|
|
||||||
debugPrint('[BeaconScan] Detected: UUID=$uuid, BeaconID=$beaconId, RSSI=$rssi');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('[BeaconScan] Error parsing beacon data: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MapEntry<String, int>? _findBestBeacon() {
|
|
||||||
if (_detectedBeacons.isEmpty) return null;
|
|
||||||
|
|
||||||
String? bestUUID;
|
|
||||||
int bestRSSI = -200;
|
|
||||||
|
|
||||||
for (final entry in _detectedBeacons.entries) {
|
|
||||||
if (entry.value.value > bestRSSI) {
|
|
||||||
bestRSSI = entry.value.value;
|
|
||||||
bestUUID = entry.key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bestUUID != null) {
|
|
||||||
final beaconId = _detectedBeacons[bestUUID]!.key;
|
|
||||||
return MapEntry(bestUUID, beaconId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _autoSelectBusinessFromBeacon(MapEntry<String, int> beacon) async {
|
|
||||||
final beaconId = beacon.value;
|
|
||||||
debugPrint('[BeaconScan] Found beacon! BeaconID=$beaconId, UUID=${beacon.key}');
|
|
||||||
|
|
||||||
// TODO: Fetch Business + ServicePoint info from BeaconID
|
|
||||||
// For now, navigate to restaurant select
|
|
||||||
_navigateToRestaurantSelect();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _navigateToRestaurantSelect() {
|
|
||||||
Navigator.of(context).pushReplacementNamed(AppRoutes.restaurantSelect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _retryPermissions() async {
|
|
||||||
await BeaconPermissions.openSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
BeaconsPlugin.stopMonitoring();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
body: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
if (_scanning)
|
|
||||||
const CircularProgressIndicator(color: Colors.white)
|
|
||||||
else if (!_permissionsGranted)
|
|
||||||
const Icon(Icons.bluetooth_disabled, color: Colors.white70, size: 64)
|
|
||||||
else
|
|
||||||
const Icon(Icons.bluetooth_searching, color: Colors.white70, size: 64),
|
|
||||||
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
Text(
|
|
||||||
_status,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
|
|
||||||
if (_detectedBeacons.isNotEmpty) ...[
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
'Found ${_detectedBeacons.length} beacon(s)',
|
|
||||||
style: const TextStyle(color: Colors.white70, fontSize: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
|
|
||||||
if (!_permissionsGranted && _status.contains('denied')) ...[
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
FilledButton(
|
|
||||||
onPressed: _retryPermissions,
|
|
||||||
child: const Text('Open Settings'),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
TextButton(
|
|
||||||
onPressed: _navigateToRestaurantSelect,
|
|
||||||
style: TextButton.styleFrom(foregroundColor: Colors.white70),
|
|
||||||
child: const Text('Skip and select manually'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -339,10 +339,6 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _addToCart(MenuItem item, Set<int> selectedModifierIds) async {
|
Future<void> _addToCart(MenuItem item, Set<int> selectedModifierIds) async {
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: _addToCart called for item ${item.name} (ItemID=${item.itemId})");
|
|
||||||
print("DEBUG: Selected modifier IDs: $selectedModifierIds");
|
|
||||||
|
|
||||||
// Check if user is logged in - if not, navigate to login
|
// Check if user is logged in - if not, navigate to login
|
||||||
if (_userId == null) {
|
if (_userId == null) {
|
||||||
final shouldLogin = await showDialog<bool>(
|
final shouldLogin = await showDialog<bool>(
|
||||||
|
|
@ -388,8 +384,6 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
servicePointId: _servicePointId!,
|
servicePointId: _servicePointId!,
|
||||||
orderTypeId: 1, // Dine-in
|
orderTypeId: 1, // Dine-in
|
||||||
);
|
);
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Created cart with orderId=${cart.orderId}");
|
|
||||||
appState.setCartOrder(
|
appState.setCartOrder(
|
||||||
orderId: cart.orderId,
|
orderId: cart.orderId,
|
||||||
orderUuid: cart.orderUuid,
|
orderUuid: cart.orderUuid,
|
||||||
|
|
@ -398,13 +392,8 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
} else {
|
} else {
|
||||||
// We have an existing cart ID
|
// We have an existing cart ID
|
||||||
cart = await Api.getCart(orderId: appState.cartOrderId!);
|
cart = await Api.getCart(orderId: appState.cartOrderId!);
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Loaded existing cart with orderId=${cart.orderId}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: About to add root item ${item.itemId} to cart ${cart.orderId}");
|
|
||||||
|
|
||||||
// Check if this item already exists in the cart (as a root item)
|
// Check if this item already exists in the cart (as a root item)
|
||||||
final existingItem = cart.lineItems.where(
|
final existingItem = cart.lineItems.where(
|
||||||
(li) => li.itemId == item.itemId && li.parentOrderLineItemId == 0 && !li.isDeleted
|
(li) => li.itemId == item.itemId && li.parentOrderLineItemId == 0 && !li.isDeleted
|
||||||
|
|
@ -412,9 +401,6 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
|
|
||||||
final newQuantity = (existingItem?.quantity ?? 0) + 1;
|
final newQuantity = (existingItem?.quantity ?? 0) + 1;
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Existing quantity: ${existingItem?.quantity ?? 0}, new quantity: $newQuantity");
|
|
||||||
|
|
||||||
// Add root item (or update quantity if it exists)
|
// Add root item (or update quantity if it exists)
|
||||||
cart = await Api.setLineItem(
|
cart = await Api.setLineItem(
|
||||||
orderId: cart.orderId,
|
orderId: cart.orderId,
|
||||||
|
|
@ -424,22 +410,12 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
quantity: newQuantity,
|
quantity: newQuantity,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Added root item, cart now has ${cart.lineItems.length} line items");
|
|
||||||
|
|
||||||
// Find the OrderLineItemID of the root item we just added
|
// Find the OrderLineItemID of the root item we just added
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Looking for root item with ItemID=${item.itemId} in ${cart.lineItems.length} line items");
|
|
||||||
print("DEBUG: Line items: ${cart.lineItems.map((li) => 'ID=${li.orderLineItemId}, ItemID=${li.itemId}, ParentID=${li.parentOrderLineItemId}').join(', ')}");
|
|
||||||
|
|
||||||
final rootLineItem = cart.lineItems.lastWhere(
|
final rootLineItem = cart.lineItems.lastWhere(
|
||||||
(li) => li.itemId == item.itemId && li.parentOrderLineItemId == 0 && !li.isDeleted,
|
(li) => li.itemId == item.itemId && li.parentOrderLineItemId == 0 && !li.isDeleted,
|
||||||
orElse: () => throw StateError('Root line item not found for ItemID=${item.itemId}'),
|
orElse: () => throw StateError('Root line item not found for ItemID=${item.itemId}'),
|
||||||
);
|
);
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Root item found - OrderLineItemID=${rootLineItem.orderLineItemId}");
|
|
||||||
|
|
||||||
// Add all selected modifiers recursively
|
// Add all selected modifiers recursively
|
||||||
await _addModifiersRecursively(
|
await _addModifiersRecursively(
|
||||||
cart.orderId,
|
cart.orderId,
|
||||||
|
|
@ -451,10 +427,6 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
// Refresh cart to get final state
|
// Refresh cart to get final state
|
||||||
cart = await Api.getCart(orderId: cart.orderId);
|
cart = await Api.getCart(orderId: cart.orderId);
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Final cart state - itemCount=${cart.itemCount}, lineItems=${cart.lineItems.length}");
|
|
||||||
print("DEBUG: Root items: ${cart.lineItems.where((li) => li.parentOrderLineItemId == 0 && !li.isDeleted).map((li) => 'ItemID=${li.itemId}, Qty=${li.quantity}, Deleted=${li.isDeleted}').join(', ')}");
|
|
||||||
|
|
||||||
appState.updateCartItemCount(cart.itemCount);
|
appState.updateCartItemCount(cart.itemCount);
|
||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
@ -483,25 +455,14 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
) async {
|
) async {
|
||||||
final children = _itemsByParent[parentItemId] ?? [];
|
final children = _itemsByParent[parentItemId] ?? [];
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: _addModifiersRecursively called with ParentItemID=$parentItemId, ParentOrderLineItemID=$parentOrderLineItemId");
|
|
||||||
print("DEBUG: Found ${children.length} children for ItemID=$parentItemId");
|
|
||||||
print("DEBUG: Children ItemIDs: ${children.map((c) => c.itemId).join(', ')}");
|
|
||||||
print("DEBUG: Selected ItemIDs: ${selectedItemIds.join(', ')}");
|
|
||||||
|
|
||||||
for (final child in children) {
|
for (final child in children) {
|
||||||
final isSelected = selectedItemIds.contains(child.itemId);
|
final isSelected = selectedItemIds.contains(child.itemId);
|
||||||
|
|
||||||
// Only add selected items to the cart
|
// Only add selected items to the cart
|
||||||
if (!isSelected) {
|
if (!isSelected) {
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Skipping unselected child ItemID=${child.itemId} (${child.name})");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Processing child ItemID=${child.itemId} (${child.name}), isSelected=$isSelected");
|
|
||||||
|
|
||||||
// Add this modifier with the correct parent OrderLineItemID
|
// Add this modifier with the correct parent OrderLineItemID
|
||||||
final cart = await Api.setLineItem(
|
final cart = await Api.setLineItem(
|
||||||
orderId: orderId,
|
orderId: orderId,
|
||||||
|
|
@ -510,18 +471,12 @@ class _MenuBrowseScreenState extends State<MenuBrowseScreen> {
|
||||||
isSelected: true,
|
isSelected: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: setLineItem response: cart has ${cart.lineItems.length} line items");
|
|
||||||
|
|
||||||
// Find the OrderLineItemID of this modifier we just added
|
// Find the OrderLineItemID of this modifier we just added
|
||||||
final childLineItem = cart.lineItems.lastWhere(
|
final childLineItem = cart.lineItems.lastWhere(
|
||||||
(li) => li.itemId == child.itemId && li.parentOrderLineItemId == parentOrderLineItemId && !li.isDeleted,
|
(li) => li.itemId == child.itemId && li.parentOrderLineItemId == parentOrderLineItemId && !li.isDeleted,
|
||||||
orElse: () => throw StateError('Child line item not found for ItemID=${child.itemId}'),
|
orElse: () => throw StateError('Child line item not found for ItemID=${child.itemId}'),
|
||||||
);
|
);
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("DEBUG: Child modifier OrderLineItemID=${childLineItem.orderLineItemId}");
|
|
||||||
|
|
||||||
// Recursively add grandchildren
|
// Recursively add grandchildren
|
||||||
await _addModifiersRecursively(
|
await _addModifiersRecursively(
|
||||||
orderId,
|
orderId,
|
||||||
|
|
|
||||||
|
|
@ -104,13 +104,6 @@ class Api {
|
||||||
final body = resp.body;
|
final body = resp.body;
|
||||||
final j = _tryDecodeJsonMap(body);
|
final j = _tryDecodeJsonMap(body);
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("API GET => $url");
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("STATUS => ${resp.statusCode}");
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("BODY => ${body.length > 2000 ? body.substring(0, 2000) : body}");
|
|
||||||
|
|
||||||
return ApiRawResponse(statusCode: resp.statusCode, rawBody: body, json: j);
|
return ApiRawResponse(statusCode: resp.statusCode, rawBody: body, json: j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,15 +122,6 @@ class Api {
|
||||||
final body = resp.body;
|
final body = resp.body;
|
||||||
final j = _tryDecodeJsonMap(body);
|
final j = _tryDecodeJsonMap(body);
|
||||||
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("API POST => $url");
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("BODY IN => ${jsonEncode(payload)}");
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("STATUS => ${resp.statusCode}");
|
|
||||||
// ignore: avoid_print
|
|
||||||
print("BODY OUT => ${body.length > 2000 ? body.substring(0, 2000) : body}");
|
|
||||||
|
|
||||||
return ApiRawResponse(statusCode: resp.statusCode, rawBody: body, json: j);
|
return ApiRawResponse(statusCode: resp.statusCode, rawBody: body, json: j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue