first commit
This commit is contained in:
52
lib/controllers/dashboard_controller/category.dart
Normal file
52
lib/controllers/dashboard_controller/category.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:get/get_rx/src/rx_types/rx_types.dart';
|
||||
import 'package:get/get_state_manager/src/simple/get_controllers.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../../modules/tenant/category.dart';
|
||||
|
||||
class CategoryController extends GetxController {
|
||||
var categories = <Category>[].obs;
|
||||
|
||||
|
||||
var isLoading = false.obs;
|
||||
var selectedIndex = 0.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
fetchCategories();
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
void fetchCategories() async {
|
||||
try {
|
||||
isLoading(true);
|
||||
|
||||
final url = Uri.parse(
|
||||
'https://fiesta.nearle.app/live/api/v1/mob/utils/getappcategories');
|
||||
|
||||
final response = await http.get(url);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
categories.value = (data['details'] as List)
|
||||
.map((e) => Category.fromJson(e))
|
||||
.toList();
|
||||
|
||||
print(response.body);
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error: $e");
|
||||
} finally {
|
||||
isLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
void selectCategory(int index) {
|
||||
selectedIndex.value = index;
|
||||
}
|
||||
}
|
||||
748
lib/controllers/dashboard_controller/dashboard_controller.dart
Normal file
748
lib/controllers/dashboard_controller/dashboard_controller.dart
Normal file
@@ -0,0 +1,748 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:lottie/lottie.dart';
|
||||
import 'package:nearledaily/constants/color_constants.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../Helper/Logger.dart';
|
||||
import '../../constants/font_constants.dart';
|
||||
import '../../data/tenant/get_tenant_res.dart';
|
||||
import '../../domain/provider/authentication/location.dart';
|
||||
import '../../domain/provider/tenant/get_tenant_pro.dart';
|
||||
import '../../domain/repository/authentication/auth_repository.dart';
|
||||
import '../../domain/repository/tenant/get_tenant_repo.dart';
|
||||
import '../../modules/authentication/auth.dart';
|
||||
import '../../modules/tenant/category.dart';
|
||||
import '../../modules/tenant/get_tenant.dart';
|
||||
import '../../view/authentication/costomer_create_view.dart';
|
||||
import '../../widgets/text_widget.dart';
|
||||
import '../tenant_controller /tenant_list.dart';
|
||||
|
||||
class DashboardController extends GetxController {
|
||||
// Loading state
|
||||
var isLoading = true.obs;
|
||||
List<Authentication> fetchedLocations = [];
|
||||
var categories = <Category>[].obs;
|
||||
|
||||
|
||||
var selectedIndex = 0.obs;
|
||||
var show = true.obs;
|
||||
|
||||
|
||||
|
||||
void fetchCategories() async {
|
||||
try {
|
||||
isLoading(true);
|
||||
|
||||
final url = Uri.parse(
|
||||
'https://fiesta.nearle.app/live/api/v1/mob/utils/getappcategories');
|
||||
|
||||
final response = await http.get(url);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
categories.value = (data['details'] as List)
|
||||
.map((e) => Category.fromJson(e))
|
||||
.toList();
|
||||
|
||||
print(response.body);
|
||||
print('gtot');
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error: $e");
|
||||
} finally {
|
||||
isLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
void selectCategory(int index) {
|
||||
selectedIndex.value = index;
|
||||
}
|
||||
|
||||
|
||||
Future<void> checkMainFlag() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
|
||||
bool firstTime = prefs.getBool("firstTime") ?? true;
|
||||
|
||||
if (firstTime) {
|
||||
show.value = true;
|
||||
|
||||
// Next time this becomes false
|
||||
prefs.setBool("firstTime", false);
|
||||
} else {
|
||||
show.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
void location(){
|
||||
_showLocationBottomSheet();
|
||||
}
|
||||
|
||||
// Carousel images
|
||||
var carouselImages = <String>[].obs;
|
||||
// List<Tenants> getAllTenants = [];
|
||||
// Grid items
|
||||
var gridItems = <Map<String, String>>[].obs;
|
||||
var currentAddress = ''.obs;
|
||||
final CustomerLocationProvider locationProvider = CustomerLocationProvider();
|
||||
final TenantController tenantController = Get.put(TenantController());
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
// loadTenants();
|
||||
_getAndUpdateCurrentLocation();
|
||||
_fetchLocations();
|
||||
checkMainFlag();
|
||||
print("🚀 DashboardController onInit() called");
|
||||
// getTenantCustomers();
|
||||
// Simulate data loading (e.g., from an API)
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
// Load carousel images
|
||||
carouselImages.addAll([
|
||||
'assets/Banner_1.png',
|
||||
'assets/Banner_2.png',
|
||||
]);
|
||||
|
||||
|
||||
|
||||
// Set loading to false after data is loaded
|
||||
isLoading.value = false;
|
||||
});
|
||||
fetchCategories();
|
||||
super.onInit();
|
||||
}
|
||||
Future<void> _fetchLocations() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
final id = prefs.getInt('customerId');
|
||||
|
||||
try {
|
||||
final locations = await locationProvider.fetchCustomerLocations(id!);
|
||||
fetchedLocations = locations;
|
||||
print(locations);
|
||||
|
||||
} catch (e) {
|
||||
print('Error fetching locations: $e');
|
||||
} finally {
|
||||
|
||||
}
|
||||
}
|
||||
void loadTenants() async {
|
||||
isLoading.value = true;
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
int? id = prefs.getInt('customerId');
|
||||
|
||||
try {
|
||||
final response = await CustomerTenantsProvider().getCustomerTenants(id!, 1);
|
||||
|
||||
if (response != null && response.status == true && response.details != null) {
|
||||
populateGridFromTenants(response);
|
||||
} else {
|
||||
gridItems.clear();
|
||||
}
|
||||
} catch (e) {
|
||||
print("⛔ Error fetching tenants: $e");
|
||||
gridItems.clear();
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
void populateGridFromTenants(CustomerTenantsResponse response) {
|
||||
final tenants = response.details ?? [];
|
||||
gridItems.clear();
|
||||
|
||||
for (var tenant in tenants) {
|
||||
gridItems.add({
|
||||
'tenantid': (tenant.tenantid ?? 0).toString(),
|
||||
'title': tenant.tenantname ?? 'No Name',
|
||||
'address': tenant.address ?? '',
|
||||
'licenseno': tenant.licenseno ?? '',
|
||||
'primaryemail': tenant.primaryemail ?? '',
|
||||
'primarycontact': tenant.primarycontact ?? '',
|
||||
'pickuplocationid': (tenant.pickuplocationid ?? 0).toString(),
|
||||
'applocationid': (tenant.applocationid ?? 0).toString(),
|
||||
'suburb': tenant.suburb ?? '',
|
||||
'city': tenant.city ?? '',
|
||||
'latitude': tenant.latitude ?? '',
|
||||
'longitude': tenant.longitude ?? '',
|
||||
'postcode': tenant.postcode ?? '',
|
||||
'tenantimage': tenant.tenantimage != null && tenant.tenantimage!.isNotEmpty
|
||||
? tenant.tenantimage!
|
||||
: 'https://via.placeholder.com/150',
|
||||
'locationid': (tenant.locationid ?? 0).toString(),
|
||||
'locationname': tenant.locationname ?? '',
|
||||
'subcategoryid': (tenant.subcategoryid ?? 0).toString(),
|
||||
'categoryid': (tenant.categoryid ?? 0).toString(),
|
||||
'registrationno': tenant.registrationno ?? '',
|
||||
});
|
||||
}
|
||||
}
|
||||
Future<void> _updateProfile({
|
||||
required String address,
|
||||
required double latitude,
|
||||
required double longitude,
|
||||
required String city,
|
||||
required String state,
|
||||
required String suburb,
|
||||
}) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
int? id = prefs.getInt('customerId');
|
||||
prefs.setDouble('lat', latitude);
|
||||
prefs.setDouble('long', longitude);
|
||||
String? name = prefs.getString('customerFirstname');
|
||||
String? contactNo = prefs.getString('contactno');
|
||||
String? fcm = prefs.getString('fcmToken');
|
||||
|
||||
if (id == null) {
|
||||
// Get.snackbar("Error", "Customer ID not found");
|
||||
return;
|
||||
}
|
||||
|
||||
final repo = LoginRepository();
|
||||
|
||||
Map<String, dynamic> data = {
|
||||
"customerid": id,
|
||||
"configid": 2,
|
||||
"address": address.toString(),
|
||||
"suburb": suburb.toString(),
|
||||
"city": city.toString(),
|
||||
"state": state.toString(),
|
||||
"latitude": latitude.toString(),
|
||||
"longitude": longitude.toString(),
|
||||
'customertoken': fcm
|
||||
};
|
||||
|
||||
print("Request Data: $data");
|
||||
// 🧾 Print all data in readable format
|
||||
print("🚀 Sending Update Profile Request:");
|
||||
print("==================================");
|
||||
print("🆔 Customer ID: $id");
|
||||
print("👤 Name: $name");
|
||||
print("📞 Contact: $contactNo");
|
||||
print("📍 Address: $address");
|
||||
print("🏙️ City: $city");
|
||||
print("🌆 State: $state");
|
||||
print("🏘️ Suburb: $suburb");
|
||||
print("🧭 Latitude: $latitude");
|
||||
print("🧭 Longitude: $longitude");
|
||||
print("🧭 fcm: $fcm");
|
||||
print("==================================");
|
||||
|
||||
|
||||
try {
|
||||
final response = await repo.updateProfile(data);
|
||||
print("Server Response: $response");
|
||||
|
||||
if (response != null && response['status'] == true) {
|
||||
tenantController.loadTenants();
|
||||
// Get.snackbar("Success", "Location updated");
|
||||
} else {
|
||||
// Get.snackbar("Error", "Something went wrong");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Update Profile Error: $e");
|
||||
// Get.snackbar("Error", "Something went wrong");
|
||||
}
|
||||
}
|
||||
Future<void> _getAndUpdateCurrentLocation() async {
|
||||
bool serviceEnabled;
|
||||
LocationPermission permission;
|
||||
|
||||
// Check if location service is enabled
|
||||
serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
// Show bottom sheet to add new address
|
||||
_showLocationBottomSheet();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check location permission
|
||||
permission = await Geolocator.checkPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
print("❌ Location permissions are denied.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (permission == LocationPermission.deniedForever) {
|
||||
print("❌ Location permissions are permanently denied.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current position
|
||||
Position position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
);
|
||||
|
||||
// Reverse geocode
|
||||
List<Placemark> placemarks =
|
||||
await placemarkFromCoordinates(position.latitude, position.longitude);
|
||||
|
||||
if (placemarks.isNotEmpty) {
|
||||
Placemark place = placemarks.first;
|
||||
|
||||
String fullAddress =
|
||||
"${place.name}, ${place.subLocality}, ${place.locality}, ${place.administrativeArea}, ${place.country}, ${place.postalCode}";
|
||||
String city = place.locality ?? '';
|
||||
String state = place.administrativeArea ?? '';
|
||||
String suburb = place.subLocality ?? '';
|
||||
|
||||
// Auto update profile
|
||||
await _updateProfile(
|
||||
address: fullAddress,
|
||||
latitude: position.latitude,
|
||||
longitude: position.longitude,
|
||||
city: city,
|
||||
state: state,
|
||||
suburb: suburb,
|
||||
);
|
||||
|
||||
|
||||
} else {
|
||||
print("⚠️ No address found for this location.");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showLocationBottomSheet() async {
|
||||
await _fetchLocations();
|
||||
|
||||
if (fetchedLocations.isEmpty) return;
|
||||
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
Get.bottomSheet(
|
||||
StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
String? selectedAddress;
|
||||
|
||||
return SafeArea(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
height: MediaQuery.of(context).size.height * 0.75,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Drag Handle
|
||||
Center(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(top: 10, bottom: 16),
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: ColorConstants.primaryColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// ── Header Row ──
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Title + subtitle
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ReusableTextWidget(
|
||||
text: 'Location & Address',
|
||||
color: Colors.black,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
ReusableTextWidget(
|
||||
text: 'Allow location access for faster delivery',
|
||||
color: Colors.grey.shade600,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Map pin illustration box
|
||||
Container(
|
||||
width: 64,
|
||||
height: 64,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFEDE7F6),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
const Icon(Icons.location_on,
|
||||
color: Color(0xFF662582), size: 32),
|
||||
Positioned(
|
||||
top: 8,
|
||||
left: 8,
|
||||
child: Icon(Icons.auto_awesome,
|
||||
color: Color(0xFF662582), size: 12),
|
||||
),
|
||||
Positioned(
|
||||
top: 12,
|
||||
left: 14,
|
||||
child: Icon(Icons.auto_awesome,
|
||||
color: Color(0xFF662582), size: 8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// ── Turn on Location Card ──
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16, vertical: 14),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF0EAFB),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Crosshair icon circle
|
||||
Container(
|
||||
width: 44,
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.08),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Icon(Icons.my_location,
|
||||
color: Color(0xFF662582), size: 22),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
// Text
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ReusableTextWidget(
|
||||
text: 'Turn on location',
|
||||
color: Colors.black,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
ReusableTextWidget(
|
||||
text: 'Detect your location automatically',
|
||||
color: Colors.grey.shade600,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// Enable button
|
||||
ElevatedButton.icon(
|
||||
onPressed: () async {
|
||||
final result =
|
||||
await Get.to(() => const MapPickerPage1());
|
||||
if (result != null &&
|
||||
result is Map<String, dynamic>) {
|
||||
await _updateProfile(
|
||||
address: result['address'] ?? '',
|
||||
latitude: double.tryParse(
|
||||
result['latitude'] ?? '0') ??
|
||||
0.0,
|
||||
longitude: double.tryParse(
|
||||
result['longitude'] ?? '0') ??
|
||||
0.0,
|
||||
city: result['city'] ?? '',
|
||||
state: result['state'] ?? '',
|
||||
suburb: result['suburb'] ?? '',
|
||||
);
|
||||
Navigator.pop(context, result);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.near_me,
|
||||
color: Colors.white, size: 16),
|
||||
label: ReusableTextWidget(
|
||||
text: 'Enable',
|
||||
color: Colors.white,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: ColorConstants.primaryColor,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 14, vertical: 10),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// ── Saved Addresses Header ──
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ReusableTextWidget(
|
||||
text: 'Saved Addresses',
|
||||
color: Colors.black,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
final result =
|
||||
await Get.to(() => const MapPickerPage1());
|
||||
if (result != null &&
|
||||
result is Map<String, dynamic>) {
|
||||
await _updateProfile(
|
||||
address: result['address'] ?? '',
|
||||
latitude: double.tryParse(
|
||||
result['latitude'] ?? '0') ??
|
||||
0.0,
|
||||
longitude: double.tryParse(
|
||||
result['longitude'] ?? '0') ??
|
||||
0.0,
|
||||
city: result['city'] ?? '',
|
||||
state: result['state'] ?? '',
|
||||
suburb: result['suburb'] ?? '',
|
||||
);
|
||||
Navigator.pop(context, result);
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.add_circle_outline,
|
||||
color: ColorConstants.primaryColor, size: 18),
|
||||
const SizedBox(width: 4),
|
||||
ReusableTextWidget(
|
||||
text: 'Add New',
|
||||
color: ColorConstants.primaryColor,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// ── Address List ──
|
||||
Expanded(
|
||||
child: fetchedLocations.isNotEmpty
|
||||
? ListView.builder(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
itemCount: fetchedLocations.length,
|
||||
itemBuilder: (context, index) {
|
||||
final loc = fetchedLocations[index];
|
||||
final addr = loc.address ?? '';
|
||||
final isSelected = selectedAddress == addr;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
setState(() => selectedAddress = addr);
|
||||
await _updateProfile(
|
||||
address: loc.address ?? '',
|
||||
latitude: double.tryParse(
|
||||
loc.latitude ?? '0') ??
|
||||
0.0,
|
||||
longitude: double.tryParse(
|
||||
loc.longitude ?? '0') ??
|
||||
0.0,
|
||||
city: loc.city ?? '',
|
||||
state: loc.state ?? '',
|
||||
suburb: loc.suburb ?? '',
|
||||
);
|
||||
Navigator.pop(context, loc);
|
||||
},
|
||||
child: Container(
|
||||
margin:
|
||||
const EdgeInsets.only(bottom: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 14),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? ColorConstants.primaryColor
|
||||
: Colors.grey.shade200,
|
||||
width: isSelected ? 1.5 : 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color:
|
||||
Colors.black.withOpacity(0.04),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Purple circle icon
|
||||
Container(
|
||||
width: 42,
|
||||
height: 42,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFEDE7F6),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.location_on,
|
||||
color: Color(0xFF662582),
|
||||
size: 22,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
// Address text
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
ReusableTextWidget(
|
||||
text: loc.suburb?.isNotEmpty ==
|
||||
true
|
||||
? loc.suburb!
|
||||
: "Address ${index + 1}",
|
||||
color: Colors.black87,
|
||||
fontFamily:
|
||||
FontConstants.fontFamily,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
ReusableTextWidget(
|
||||
text: addr,
|
||||
color: Colors.grey.shade600,
|
||||
fontFamily:
|
||||
FontConstants.fontFamily,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// Current badge or chevron
|
||||
if (isSelected)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFE8F5E9),
|
||||
borderRadius:
|
||||
BorderRadius.circular(20),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration:
|
||||
const BoxDecoration(
|
||||
color: Colors.green,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
ReusableTextWidget(
|
||||
text: 'Current',
|
||||
color: Colors.green.shade700,
|
||||
fontFamily:
|
||||
FontConstants.fontFamily,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
Icon(Icons.chevron_right,
|
||||
color: Colors.grey.shade400,
|
||||
size: 22),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: const Center(
|
||||
child: Text(
|
||||
"No saved addresses found.",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
isScrollControlled: true,
|
||||
);
|
||||
}
|
||||
// Add method to update grid dynamically if needed
|
||||
void addGridItem(Map<String, String> item) {
|
||||
gridItems.add(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user