From 9cf652880432dd9b1551e4fdbe1a7fc1d17c42f0 Mon Sep 17 00:00:00 2001 From: shuence Date: Sun, 25 Feb 2024 21:31:39 +0530 Subject: [PATCH] Added NGO's on Map --- lib/screens/ngo/ngo_form.dart | 91 ++++++++++++++++++- lib/screens/ngo/ngo_information.dart | 2 - lib/widgets/foodcards/nearby_daily_cards.dart | 15 +-- lib/widgets/foodcards/nearby_food_cards.dart | 54 +++++------ lib/widgets/foodcards/past_food_cards.dart | 16 ++-- lib/widgets/maps_widget.dart | 53 ++++++++++- pubspec.yaml | 2 +- 7 files changed, 184 insertions(+), 49 deletions(-) diff --git a/lib/screens/ngo/ngo_form.dart b/lib/screens/ngo/ngo_form.dart index de84478..39e4a41 100644 --- a/lib/screens/ngo/ngo_form.dart +++ b/lib/screens/ngo/ngo_form.dart @@ -14,7 +14,9 @@ import 'package:spoonshare/models/users/user.dart'; import 'package:spoonshare/screens/ngo/ngo_home.dart'; import 'package:spoonshare/widgets/bottom_navbar.dart'; import 'package:spoonshare/widgets/custom_text_field.dart'; +import 'package:spoonshare/widgets/auto_complete.dart'; import 'package:spoonshare/widgets/snackbar.dart'; +import 'package:uuid/uuid.dart'; class NGOFormScreen extends StatefulWidget { const NGOFormScreen({Key? key}) : super(key: key); @@ -35,8 +37,8 @@ class NGOFormScreenState extends State { @override void initState() { super.initState(); - // Fetch user profile data fetchUserProfileData(); + _addressController.addListener(onModify); } Future fetchUserProfileData() async { @@ -58,7 +60,56 @@ class NGOFormScreenState extends State { File? _imageFile; late double lat; late double lng; - // final bool _addressSelected = false; + bool _addressSelected = false; + + String tokenForSession = "12345"; + List> listForPlaces = []; + var uuid = const Uuid(); + + Future makeSuggestions(String input) async { + try { + var suggestions = await PlaceApi.getSuggestions(input); + setState(() { + listForPlaces = suggestions; + }); + } catch (e) { + print("Error: $e"); + } + } + + @override + void dispose() { + _addressController.dispose(); + super.dispose(); + } + + void onModify() { + if (tokenForSession.isEmpty) { + setState(() { + tokenForSession = uuid.v4(); + }); + } + makeSuggestions(_addressController.text); + } + + Future handleListItemTap(int index) async { + String placeId = listForPlaces[index]['place_id']; + var placeDetails = await PlaceApi.getPlaceDetails(placeId); + double selectedLat = placeDetails['geometry']['location']['lat']; + double selectedLng = placeDetails['geometry']['location']['lng']; + String selectedAddress = listForPlaces[index]['description']; + print(selectedAddress); + print(selectedLat); + print(selectedLng); + + setState(() { + _addressController.text = selectedAddress; + lat = + selectedLat; // Update the class-level variables with the selected values + lng = selectedLng; + _addressSelected = true; // Set _addressSelected to true + }); + } bool _validateFields() { return _ngoNameController.text.isNotEmpty && @@ -73,6 +124,8 @@ class NGOFormScreenState extends State { @override Widget build(BuildContext context) { + bool showExpandedList = + _addressController.text.isNotEmpty && !_addressSelected; return Scaffold( appBar: AppBar( title: const Text('NGO Form'), @@ -204,6 +257,36 @@ class NGOFormScreenState extends State { label: 'Address*', controller: _addressController, ), + if (showExpandedList) + Container( + height: 200, // Set the height of the suggestions container + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: const Offset(0, 3), + ), + ], + ), + child: ListView.builder( + itemCount: listForPlaces.length, + itemBuilder: (context, index) { + return ListTile( + onTap: () async { + _addressSelected = true; + await handleListItemTap(index); + }, + title: Text( + listForPlaces[index]['description'], + ), + ); + }, + ), + ), const SizedBox(height: 16), CustomTextField( label: 'LinkedIn/Instagram Profile Links*', @@ -406,6 +489,9 @@ class NGOFormScreenState extends State { _imageFile, _ngoNameController.text, ); + + GeoPoint location = GeoPoint(lat, lng); + await FirebaseFirestore.instance.collection('ngos').add({ 'ngoName': _ngoNameController.text, 'mobileNo': _mobileNoController.text, @@ -415,6 +501,7 @@ class NGOFormScreenState extends State { 'incorporationDay': _selectedIncorporationDay, 'description': _decripationController.text, 'address': _addressController.text, + 'location': location, 'linkedin': _linkedinController.text, 'verified': false, }); diff --git a/lib/screens/ngo/ngo_information.dart b/lib/screens/ngo/ngo_information.dart index c86b6af..4ccf64b 100644 --- a/lib/screens/ngo/ngo_information.dart +++ b/lib/screens/ngo/ngo_information.dart @@ -4,12 +4,10 @@ import 'dart:io'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_storage/firebase_storage.dart' as firebase_storage; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:spoonshare/models/users/user.dart'; import 'package:spoonshare/screens/ngo/ngo_home.dart'; import 'package:spoonshare/widgets/bottom_navbar.dart'; diff --git a/lib/widgets/foodcards/nearby_daily_cards.dart b/lib/widgets/foodcards/nearby_daily_cards.dart index f33514d..b0f154a 100644 --- a/lib/widgets/foodcards/nearby_daily_cards.dart +++ b/lib/widgets/foodcards/nearby_daily_cards.dart @@ -80,12 +80,15 @@ class NearbyDailyFoodCard extends StatelessWidget { children: [ const Icon(Icons.location_on, size: 16), const SizedBox(width: 4), - Text( - data['venue'], - style: const TextStyle( - fontSize: 16, - fontFamily: 'DM Sans', - fontWeight: FontWeight.w700, + Flexible( + child: Text( + data['venue'], + style: const TextStyle( + fontSize: 16, + fontFamily: 'DM Sans', + fontWeight: FontWeight.w700, + ), + textAlign: TextAlign.center, ), ), const SizedBox(width: 8), diff --git a/lib/widgets/foodcards/nearby_food_cards.dart b/lib/widgets/foodcards/nearby_food_cards.dart index d197b3b..0750542 100644 --- a/lib/widgets/foodcards/nearby_food_cards.dart +++ b/lib/widgets/foodcards/nearby_food_cards.dart @@ -78,13 +78,16 @@ class NearbyFoodCard extends StatelessWidget { Row( children: [ const Icon(Icons.location_on, size: 16), - const SizedBox(width: 4), - Text( - data['venue'], - style: const TextStyle( - fontSize: 16, - fontFamily: 'DM Sans', - fontWeight: FontWeight.w700, + const SizedBox(height: 6), + Flexible( + child: Text( + data['venue'], + style: const TextStyle( + fontSize: 16, + fontFamily: 'DM Sans', + fontWeight: FontWeight.w700, + ), + textAlign: TextAlign.center, ), ), const SizedBox(width: 8), // Add some spacing here @@ -239,27 +242,26 @@ class NearbyFoodCard extends StatelessWidget { } // Function to check if the food item is past its expiration date -bool isPast(Map data) { - String toDateString = data['toDate']?.trim() ?? ''; - String toTimeString = data['toTime']?.trim() ?? ''; + bool isPast(Map data) { + String toDateString = data['toDate']?.trim() ?? ''; + String toTimeString = data['toTime']?.trim() ?? ''; - // Parse to date and time - DateTime toDate = DateFormat('yyyy-MM-dd').parse(toDateString); - DateTime toTime = DateFormat('hh:mm a').parse(toTimeString); + // Parse to date and time + DateTime toDate = DateFormat('yyyy-MM-dd').parse(toDateString); + DateTime toTime = DateFormat('hh:mm a').parse(toTimeString); - // Combine date and time into a single DateTime object - DateTime combinedDateTime = DateTime( - toDate.year, - toDate.month, - toDate.day, - toTime.hour, - toTime.minute, - ); - - // Format the current date and time - DateTime currentDateTime = DateTime.now(); + // Combine date and time into a single DateTime object + DateTime combinedDateTime = DateTime( + toDate.year, + toDate.month, + toDate.day, + toTime.hour, + toTime.minute, + ); - return combinedDateTime.isBefore(currentDateTime); -} + // Format the current date and time + DateTime currentDateTime = DateTime.now(); + return combinedDateTime.isBefore(currentDateTime); + } } diff --git a/lib/widgets/foodcards/past_food_cards.dart b/lib/widgets/foodcards/past_food_cards.dart index 6a6d37d..33e796a 100644 --- a/lib/widgets/foodcards/past_food_cards.dart +++ b/lib/widgets/foodcards/past_food_cards.dart @@ -80,13 +80,15 @@ class PastFoodCard extends StatelessWidget { children: [ const Icon(Icons.location_on, size: 16), const SizedBox(width: 4), - Text( - data['venue'], - style: const TextStyle( - fontSize: 16, - fontFamily: 'DM Sans', - color: Colors.white, - fontWeight: FontWeight.w700, + Flexible( + child: Text( + data['venue'], + style: const TextStyle( + fontSize: 16, + fontFamily: 'DM Sans', + fontWeight: FontWeight.w700, + ), + textAlign: TextAlign.center, ), ), const SizedBox(width: 8), // Add some spacing here diff --git a/lib/widgets/maps_widget.dart b/lib/widgets/maps_widget.dart index d4375ab..37812a0 100644 --- a/lib/widgets/maps_widget.dart +++ b/lib/widgets/maps_widget.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:ui' as Codec; -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -8,6 +7,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:intl/intl.dart'; import 'package:location/location.dart' as location; import 'package:permission_handler/permission_handler.dart'; +import 'package:spoonshare/screens/admin/all_ngos.dart'; import 'package:spoonshare/screens/fooddetails/food_details.dart'; import 'package:spoonshare/widgets/bottom_navbar.dart'; @@ -20,6 +20,7 @@ class _MapsWidgetState extends State { late GoogleMapController mapController; location.LocationData? currentLocation; late BitmapDescriptor customMarkerIcon; + late BitmapDescriptor customNgoMarkerIcon; @override void initState() { @@ -58,27 +59,41 @@ class _MapsWidgetState extends State { ); } + void _navigateToNgoDetails(BuildContext context, QueryDocumentSnapshot data) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ngoDetailsPage(ngoDoc: data), + ), + ); + } + Future _loadCustomMarker() async { Uint8List markerIcon = await getBytesFromAsset('assets/images/marker_icon.png', 100); customMarkerIcon = BitmapDescriptor.fromBytes(markerIcon); + + // Load a different marker for NGOs + Uint8List ngoMarkerIcon = + await getBytesFromAsset('assets/images/ngo.png', 100); + customNgoMarkerIcon = BitmapDescriptor.fromBytes(ngoMarkerIcon); } Future> _initializeMap() async { List markers = []; - QuerySnapshot querySnapshot = await FirebaseFirestore.instance + // Add markers for shared food + QuerySnapshot sharedFoodSnapshot = await FirebaseFirestore.instance .collection('food') .doc('sharedfood') .collection('foodData') .get(); - for (var doc in querySnapshot.docs) { + for (var doc in sharedFoodSnapshot.docs) { double lat = doc['location'].latitude; double lng = doc['location'].longitude; String venue = doc['venue']; bool dailyActive = doc['dailyActive'] ?? true; - bool isVerified = doc['verified'] ?? true; if (!dailyActive) { @@ -115,12 +130,40 @@ class _MapsWidgetState extends State { infoWindow: infoWindow, icon: customMarkerIcon, ); - markers.add(marker); } } } + // Add markers for NGOs + QuerySnapshot ngoSnapshot = await FirebaseFirestore.instance + .collection('ngos') + .where('verified', isEqualTo: true) + .get(); + + for (var doc in ngoSnapshot.docs) { + double lat = doc['location'].latitude; + double lng = doc['location'].longitude; + String name = doc['name']; + + InfoWindow infoWindow = InfoWindow( + title: name, + snippet: "NGO location", + onTap: () { + _navigateToNgoDetails(context, doc); + }, + ); + + Marker marker = Marker( + markerId: MarkerId('$lat,$lng'), + position: LatLng(lat, lng), + infoWindow: infoWindow, + icon: customNgoMarkerIcon, + ); + + markers.add(marker); + } + return markers; } diff --git a/pubspec.yaml b/pubspec.yaml index b9805b9..da27e7e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: spoonshare description: "Meals of Grace." publish_to: 'none' -version: 1.1.0 +version: 1.2.0 environment: sdk: '>=3.2.4 <4.0.0'