From 8fb51c1283c7785262abeb61b46f0a679fb56818 Mon Sep 17 00:00:00 2001 From: ch1nru5t Date: Sat, 29 Jul 2023 21:30:13 +0530 Subject: [PATCH 1/3] google map working --- lib/customWidgets/custom_text_form_field.dart | 50 +++--- lib/features/api/api.dart | 17 ++- lib/features/auth/services/auth_service.dart | 4 +- .../screens/explore_maps_screen.dart | 143 +++++++++++++++++- .../widgets/destination_container.dart | 106 +++++++++++++ lib/features/home/screens/home_screen.dart | 113 +------------- .../home/screens/mobile_home_screen.dart | 114 ++++++++++++++ .../home/screens/web_home_screen.dart | 77 ++++++++++ lib/main.dart | 4 + lib/models/destination_model.dart | 70 +++++++++ lib/providers/map_provider.dart | 30 ++++ pubspec.lock | 101 +++++++++++++ pubspec.yaml | 4 +- web/index.html | 87 +++++------ 14 files changed, 742 insertions(+), 178 deletions(-) create mode 100644 lib/features/explore_maps/widgets/destination_container.dart create mode 100644 lib/features/home/screens/mobile_home_screen.dart create mode 100644 lib/features/home/screens/web_home_screen.dart create mode 100644 lib/models/destination_model.dart create mode 100644 lib/providers/map_provider.dart diff --git a/lib/customWidgets/custom_text_form_field.dart b/lib/customWidgets/custom_text_form_field.dart index 33b76f6..fbbf1e9 100644 --- a/lib/customWidgets/custom_text_form_field.dart +++ b/lib/customWidgets/custom_text_form_field.dart @@ -19,12 +19,19 @@ class CustomTextFormField extends StatelessWidget { label: label, controller: controller, ) - : TextFormField( - controller: controller, - keyboardType: keyboardType, - decoration: InputDecoration( - border: const OutlineInputBorder(), - labelText: label, + : AutofillGroup( + child: TextFormField( + autofillHints: [ + keyboardType == TextInputType.emailAddress + ? AutofillHints.username + : AutofillHints.name + ], + controller: controller, + keyboardType: keyboardType, + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: label, + ), ), ); } @@ -47,20 +54,23 @@ class _PasswordFieldState extends State { bool obscure = true; @override Widget build(BuildContext context) { - return TextFormField( - controller: widget.controller, - obscureText: obscure, - keyboardType: widget.keyboardType, - decoration: InputDecoration( - border: const OutlineInputBorder(), - labelText: widget.label, - suffixIcon: IconButton( - onPressed: () { - setState(() { - obscure = !obscure; - }); - }, - icon: Icon(obscure ? Icons.visibility : Icons.visibility_off), + return AutofillGroup( + child: TextFormField( + autofillHints: const [AutofillHints.password], + controller: widget.controller, + obscureText: obscure, + keyboardType: widget.keyboardType, + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: widget.label, + suffixIcon: IconButton( + onPressed: () { + setState(() { + obscure = !obscure; + }); + }, + icon: Icon(obscure ? Icons.visibility : Icons.visibility_off), + ), ), ), ); diff --git a/lib/features/api/api.dart b/lib/features/api/api.dart index 803bfc4..674cdab 100644 --- a/lib/features/api/api.dart +++ b/lib/features/api/api.dart @@ -5,7 +5,7 @@ import 'package:http/http.dart' as http; import '../../models/user_model.dart'; class Api { - static Future<(String?, User?)> postRequest( + static Future<(String?, dynamic)> postRequest( {required String url, Map? body, Map? headers}) async { @@ -22,4 +22,19 @@ class Api { return (e.toString(), null); } } + + static Future<(String?, dynamic)> getRequest( + {required String url, Map? headers}) async { + http.Response response; + try { + response = await http.get(Uri.parse(url), headers: headers); + if (response.statusCode == 200) { + return (null, jsonDecode(response.body)); + } else { + return (jsonDecode(response.body)['error'] as String, null); + } + } catch (e) { + return (e.toString(), null); + } + } } diff --git a/lib/features/auth/services/auth_service.dart b/lib/features/auth/services/auth_service.dart index dd61031..ed85104 100644 --- a/lib/features/auth/services/auth_service.dart +++ b/lib/features/auth/services/auth_service.dart @@ -8,7 +8,7 @@ class AuthService { return await Api.postRequest( url: '${Env.baseUrl}/api/v1/signin', headers: {'Content-Type': 'application/json'}, - body: {'email': email, 'password': password}); + body: {'email': email, 'password': password}) as (String?, User?); } Future<(String?, User?)> signUp({ @@ -26,6 +26,6 @@ class AuthService { 'name': name, 'phone': phone, 'userName': userName - }); + }) as (String?, User?); } } diff --git a/lib/features/explore_maps/screens/explore_maps_screen.dart b/lib/features/explore_maps/screens/explore_maps_screen.dart index 70d1ecd..152eb00 100644 --- a/lib/features/explore_maps/screens/explore_maps_screen.dart +++ b/lib/features/explore_maps/screens/explore_maps_screen.dart @@ -1,12 +1,147 @@ +import 'dart:async'; + +import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:travel_planner_pro/features/explore_maps/widgets/destination_container.dart'; + +import '../../../models/destination_model.dart'; +import '../../../providers/map_provider.dart'; -class ExploreMapsScreen extends StatelessWidget { +class ExploreMapsScreen extends StatefulWidget { const ExploreMapsScreen({super.key}); @override - Widget build(BuildContext context) { - return const Center( - child: Text('Explore Maps Screen'), + State createState() => _ExploreMapsScreenState(); +} + +class _ExploreMapsScreenState extends State { + final Completer _controller = + Completer(); + (String?, List?)? locationList; + @override + void initState() { + super.initState(); + fetchLocationList(); + } + + void onTap(int index) async { + final GoogleMapController controller = await _controller.future; + await controller.animateCamera( + CameraUpdate.newCameraPosition( + CameraPosition( + target: LatLng(double.parse(locationList!.$2![index].latitude), + double.parse(locationList!.$2![index].longitude)), + zoom: 14.4746), + ), ); } + + void fetchLocationList() { + context.read().fetchLocationList(context).then((value) { + locationList = value; + if (value.$1 == null) { + makeMarkers(value.$2); + } + setState(() {}); + }); + } + + (List?, List?) makeMarkers( + List? destinations) { + List markers = []; + List cameraPositions = []; + for (var element in destinations!) { + markers.add(Marker( + markerId: MarkerId(element.destinationName), + position: LatLng( + double.parse(element.latitude), + double.parse(element.longitude), + ), + infoWindow: InfoWindow( + title: element.destinationName, + snippet: element.cityName, + ), + )); + cameraPositions.add(CameraPosition( + target: LatLng( + double.parse(element.latitude), + double.parse(element.longitude), + ), + zoom: 14.4746, + )); + } + return (markers, cameraPositions); + } + + @override + Widget build(BuildContext context) { + return locationList == null + ? const CircularProgressIndicator() + : locationList!.$1 == null + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + flex: 4, + child: GoogleMap( + onMapCreated: (GoogleMapController controller) { + _controller.complete(controller); + }, + markers: + Set.of(makeMarkers(locationList!.$2!).$1!), + mapType: MapType.normal, + initialCameraPosition: CameraPosition( + target: LatLng( + double.parse(locationList!.$2!.first.latitude), + double.parse( + locationList!.$2!.first.longitude, + ), + ), + zoom: 14.4746, + ), + ), + ), + Expanded( + child: CarouselSlider.builder( + itemCount: locationList!.$2!.length, + itemBuilder: (context, index, realIndex) { + return DestinationContainer( + index: index, + onTap: (int val) { + onTap(val); + }, + src: locationList!.$2![index].images.first, + placeName: + locationList!.$2![index].destinationName, + averageTravelExpenses: + locationList!.$2![index].avgTravelExpenses); + }, + options: CarouselOptions( + viewportFraction: 1 / 4, + scrollPhysics: const BouncingScrollPhysics(), + enableInfiniteScroll: false, + )) + // FlutterCarousel.builder( + // itemCount: locationList!.$2!.length, + // itemBuilder: (context, index, realIndex) { + // return DestinationContainer( + // src: locationList!.$2![index].images.first, + // placeName: locationList!.$2![index].destinationName, + // averageTravelExpenses: + // locationList!.$2![index].avgTravelExpenses); + // }, + // options: CarouselOptions( + // disableCenter: true, + // physics: const BouncingScrollPhysics(), + // viewportFraction: 0.3, + // scrollDirection: Axis.horizontal, + // ), + // ), + ) + ], + ) + : Text(locationList!.$1!); + } } diff --git a/lib/features/explore_maps/widgets/destination_container.dart b/lib/features/explore_maps/widgets/destination_container.dart new file mode 100644 index 0000000..8826f3f --- /dev/null +++ b/lib/features/explore_maps/widgets/destination_container.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; + +class DestinationContainer extends StatelessWidget { + const DestinationContainer( + {super.key, + required this.src, + required this.placeName, + required this.averageTravelExpenses, + required this.onTap, + required this.index}); + final String src; + final Function(int) onTap; + final int index; + final String placeName; + final String averageTravelExpenses; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => onTap(index), + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + image: DecorationImage( + fit: BoxFit.cover, + image: NetworkImage(src), + ), + ), + child: Align( + alignment: Alignment.bottomCenter, + child: Container( + height: MediaQuery.sizeOf(context).height * 0.1, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(8), + bottomRight: Radius.circular(8)), + color: Colors.white, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + FittedBox(child: Text(placeName)), + const Divider(), + FittedBox(child: Text(averageTravelExpenses)), + ], + ), + ), + ), + ), + + // Stack(children: [ + // Image.network(widget.src), + + // // TODO: change to cached network image + // Container( + // decoration: const BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(14), + // bottomRight: Radius.circular(14)), + // ), + // height: MediaQuery.sizeOf(context).height * 0.7, + // width: MediaQuery.sizeOf(context).width * 1, + // child: Column( + // children: [ + // Text(widget.placeName), + // Text(widget.averageTravelExpenses), + // ], + // ), + // ), + + // // Column( + // // crossAxisAlignment: CrossAxisAlignment.stretch, + // // children: [ + // // const Expanded( + // // child: SizedBox(), + // // ), + // // Expanded( + // // flex: 2, + // // child: Container( + // // decoration: const BoxDecoration( + // // color: Colors.white, + // // borderRadius: BorderRadius.only( + // // bottomLeft: Radius.circular(14), + // // bottomRight: Radius.circular(14), + // // ), + // // ), + // // child: Column( + // // children: [ + // // Text(widget.placeName), + // // const Divider(), + // // Text(widget.averageTravelExpenses), + // // ], + // // ), + // // ), + // // ), + // // ], + // // ) + // ]), + ), + ); + } +} diff --git a/lib/features/home/screens/home_screen.dart b/lib/features/home/screens/home_screen.dart index fe0d918..aaf6689 100644 --- a/lib/features/home/screens/home_screen.dart +++ b/lib/features/home/screens/home_screen.dart @@ -1,116 +1,15 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:travel_planner_pro/constants/extensions/extensions.dart'; -import 'package:travel_planner_pro/features/explore_destination/screens/explore_destination_screen.dart'; -import 'package:travel_planner_pro/features/itinerary/screens/itinerary_screen.dart'; -import 'package:travel_planner_pro/providers/auth_provider.dart'; +import 'package:travel_planner_pro/customWidgets/responsive_widget.dart'; +import 'package:travel_planner_pro/features/home/screens/mobile_home_screen.dart'; +import 'package:travel_planner_pro/features/home/screens/web_home_screen.dart'; -import '../../../constants/colors/custom_colors.dart'; -import '../../explore_maps/screens/explore_maps_screen.dart'; - -class HomeScreen extends StatefulWidget { +class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); static const String routeName = '/home-screen'; - @override - State createState() => _HomeScreenState(); -} - -class _HomeScreenState extends State { - int selectedIndex = 0; - - void setSelectedIndex(int index) { - setState(() { - selectedIndex = index; - }); - } - - List screens = [ - const ItineraryScreen(), - const ExploreDestinationScreen(), - const ExploreMapsScreen(), - ]; - @override Widget build(BuildContext context) { - return Scaffold( - drawer: Drawer( - child: ListView( - children: [ - DrawerHeader( - child: FittedBox( - child: Text( - 'Travel Planner', - style: TextStyle(color: CustomColors.yellow), - ), - ), - ), - ListTile( - tileColor: selectedIndex == 0 ? Colors.grey.shade300 : null, - title: const Text('Itinerary'), - trailing: const Icon(Icons.notes_outlined), - onTap: () { - setSelectedIndex(0); - Navigator.pop(context); - }, - ), - ListTile( - tileColor: selectedIndex == 1 ? Colors.grey.shade300 : null, - title: const Text('Explore Destination'), - trailing: const Icon(Icons.location_on_rounded), - onTap: () { - setSelectedIndex(1); - Navigator.pop(context); - }, - ), - ListTile( - tileColor: selectedIndex == 2 ? Colors.grey.shade300 : null, - title: const Text('Explore Maps'), - trailing: const Icon(Icons.map_outlined), - onTap: () { - setSelectedIndex(2); - Navigator.pop(context); - }, - ), - ], - ), - ), - appBar: AppBar( - title: const Text('Travel Planner'), - actions: [ - ClipRRect( - borderRadius: BorderRadius.circular(20), - child: Material( - child: PopupMenuButton( - tooltip: '', - child: const CircleAvatar( - backgroundImage: AssetImage('assets/images/user.jpg'), - ), - itemBuilder: (context) { - return [ - PopupMenuItem( - onTap: () { - context.read().clearUser(); - Navigator.pop(context); - // Navigator.pushNamedAndRemoveUntil( - // context, - // LandingScreen.routeName, - // (_) => true, - // ); - }, - child: const Text( - ('Logout'), - ), - ), - ]; - }, - ), - ), - ), - 20.width, - ], - ), - body: screens[selectedIndex], - ); + return const ResponsiveWidget( + mobile: MobileHomeScreen(), web: WebHomeScreen()); } } diff --git a/lib/features/home/screens/mobile_home_screen.dart b/lib/features/home/screens/mobile_home_screen.dart new file mode 100644 index 0000000..9e55e61 --- /dev/null +++ b/lib/features/home/screens/mobile_home_screen.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:travel_planner_pro/constants/extensions/extensions.dart'; + +import '../../../constants/colors/custom_colors.dart'; +import '../../../providers/auth_provider.dart'; +import '../../explore_destination/screens/explore_destination_screen.dart'; +import '../../explore_maps/screens/explore_maps_screen.dart'; +import '../../itinerary/screens/itinerary_screen.dart'; + +class MobileHomeScreen extends StatefulWidget { + const MobileHomeScreen({super.key}); + + @override + State createState() => _MobileHomeScreenState(); +} + +class _MobileHomeScreenState extends State { + void setSelectedIndex(int index) { + setState(() { + selectedIndex = index; + }); + } + + int selectedIndex = 0; + + List screens = [ + const ItineraryScreen(), + const ExploreDestinationScreen(), + const ExploreMapsScreen(), + ]; + @override + Widget build(BuildContext context) { + return Scaffold( + drawer: Drawer( + child: ListView( + children: [ + DrawerHeader( + child: FittedBox( + child: Text( + 'Travel Planner', + style: TextStyle(color: CustomColors.yellow), + ), + ), + ), + ListTile( + tileColor: selectedIndex == 0 ? Colors.grey.shade300 : null, + title: const Text('Itinerary'), + trailing: const Icon(Icons.notes_outlined), + onTap: () { + setSelectedIndex(0); + Navigator.pop(context); + }, + ), + ListTile( + tileColor: selectedIndex == 1 ? Colors.grey.shade300 : null, + title: const Text('Explore Destination'), + trailing: const Icon(Icons.location_on_rounded), + onTap: () { + setSelectedIndex(1); + Navigator.pop(context); + }, + ), + ListTile( + tileColor: selectedIndex == 2 ? Colors.grey.shade300 : null, + title: const Text('Explore Maps'), + trailing: const Icon(Icons.map_outlined), + onTap: () { + setSelectedIndex(2); + Navigator.pop(context); + }, + ), + ], + ), + ), + appBar: AppBar( + title: const Text('Travel Planner'), + actions: [ + ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Material( + child: PopupMenuButton( + tooltip: '', + child: const CircleAvatar( + backgroundImage: AssetImage('assets/images/user.jpg'), + ), + itemBuilder: (context) { + return [ + PopupMenuItem( + onTap: () { + context.read().clearUser(); + Navigator.pop(context); + // Navigator.pushNamedAndRemoveUntil( + // context, + // LandingScreen.routeName, + // (_) => true, + // ); + }, + child: const Text( + ('Logout'), + ), + ), + ]; + }, + ), + ), + ), + 20.width, + ], + ), + body: screens[selectedIndex], + ); + } +} diff --git a/lib/features/home/screens/web_home_screen.dart b/lib/features/home/screens/web_home_screen.dart new file mode 100644 index 0000000..9c44778 --- /dev/null +++ b/lib/features/home/screens/web_home_screen.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; + +import '../../../constants/colors/custom_colors.dart'; +import '../../explore_destination/screens/explore_destination_screen.dart'; +import '../../explore_maps/screens/explore_maps_screen.dart'; +import '../../itinerary/screens/itinerary_screen.dart'; + +class WebHomeScreen extends StatefulWidget { + const WebHomeScreen({super.key}); + + @override + State createState() => _WebHomeScreenState(); +} + +class _WebHomeScreenState extends State { + int selectedIndex = 0; + + void setSelectedIndex(int index) { + setState(() { + selectedIndex = index; + }); + } + + List screens = [ + const ItineraryScreen(), + const ExploreDestinationScreen(), + const ExploreMapsScreen(), + ]; + @override + Widget build(BuildContext context) { + return Scaffold( + body: Row( + children: [ + Expanded( + child: ListView( + children: [ + DrawerHeader( + child: FittedBox( + child: Text( + 'Travel Planner', + style: TextStyle(color: CustomColors.yellow), + ), + ), + ), + ListTile( + tileColor: selectedIndex == 0 ? Colors.grey.shade300 : null, + title: const Text('Itinerary'), + trailing: const Icon(Icons.notes_outlined), + onTap: () { + setSelectedIndex(0); + }, + ), + ListTile( + tileColor: selectedIndex == 1 ? Colors.grey.shade300 : null, + title: const Text('Explore Destination'), + trailing: const Icon(Icons.location_on_rounded), + onTap: () { + setSelectedIndex(1); + }, + ), + ListTile( + tileColor: selectedIndex == 2 ? Colors.grey.shade300 : null, + title: const Text('Explore Maps'), + trailing: const Icon(Icons.map_outlined), + onTap: () { + setSelectedIndex(2); + }, + ), + ], + ), + ), + Expanded(flex: 4, child: screens[selectedIndex]), + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index e753973..d24278a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:provider/provider.dart'; import 'package:travel_planner_pro/constants/colors/custom_colors.dart'; import 'package:travel_planner_pro/features/landing_page/screens/landing_screen.dart'; import 'package:travel_planner_pro/providers/auth_provider.dart'; +import 'package:travel_planner_pro/providers/map_provider.dart'; import 'package:travel_planner_pro/router.dart'; void main() { @@ -13,6 +14,9 @@ void main() { ChangeNotifierProvider( create: (_) => AuthProvider(), ), + ChangeNotifierProvider( + create: (_) => MapProvider(), + ), ], child: const MyApp(), ), diff --git a/lib/models/destination_model.dart b/lib/models/destination_model.dart new file mode 100644 index 0000000..a50e247 --- /dev/null +++ b/lib/models/destination_model.dart @@ -0,0 +1,70 @@ +import 'dart:convert'; + +class Destination { + String destinationName; + String cityName; + String latitude; + String longitude; + List landmarks; + String state; + String description; + List images; + String avgTravelExpenses; + List attractions; + String category; + Destination({ + required this.destinationName, + required this.cityName, + required this.latitude, + required this.longitude, + required this.landmarks, + required this.state, + required this.description, + required this.images, + required this.avgTravelExpenses, + required this.attractions, + required this.category, + }); + + Map toMap() { + return { + 'destinationName': destinationName, + 'cityName': cityName, + 'latitude': latitude, + 'longitude': longitude, + 'landmarks': landmarks, + 'state': state, + 'description': description, + 'images': images, + 'avgTravelExpenses': avgTravelExpenses, + 'attractions': attractions, + 'category': category, + }; + } + + factory Destination.fromMap(Map map) { + return Destination( + destinationName: map['destinationName'] as String, + cityName: map['cityName'] as String, + latitude: map['latitude'] as String, + longitude: map['longitude'] as String, + landmarks: map['landmarks'] as List, + state: map['state'] as String, + description: map['description'] as String, + images: map['images'] as List, + avgTravelExpenses: map['avgTravelExpenses'] as String, + attractions: map['attractions'] as List, + category: map['category'] as String, + ); + } + + String toJson() => json.encode(toMap()); + + factory Destination.fromJson(String source) => + Destination.fromMap(json.decode(source) as Map); + + @override + String toString() { + return 'Destination(destinationName: $destinationName, cityName: $cityName, latitude: $latitude, longitude: $longitude, landmarks: $landmarks, state: $state, description: $description, images: $images, avgTravelExpenses: $avgTravelExpenses, attractions: $attractions, category: $category)'; + } +} diff --git a/lib/providers/map_provider.dart b/lib/providers/map_provider.dart new file mode 100644 index 0000000..2752baf --- /dev/null +++ b/lib/providers/map_provider.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:travel_planner_pro/env/env.dart'; +import 'package:travel_planner_pro/features/api/api.dart'; +import 'package:travel_planner_pro/models/destination_model.dart'; + +import 'auth_provider.dart'; + +class MapProvider extends ChangeNotifier { + Future<(String?, List?)> fetchLocationList( + BuildContext context) async { + (String?, dynamic) response = await Api.getRequest( + url: '${Env.baseUrl}/api/v1/get-all-destinations', + headers: { + 'Authorization': 'Bearer ${context.read().user!.token}' + }); + if (response.$1 == null) { + // success + Map json = response.$2; + List destinationList = []; + json['data'].forEach((element) { + destinationList.add(Destination.fromMap(element)); + }); + return (null, destinationList); + } else { + // error + return (response.$1, null); + } + } +} diff --git a/pubspec.lock b/pubspec.lock index 0ee33f1..beecda0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.6.1" + carousel_slider: + dependency: "direct main" + description: + name: carousel_slider + sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42" + url: "https://pub.dev" + source: hosted + version: "4.2.1" characters: dependency: transitive description: @@ -169,6 +177,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" cupertino_icons: dependency: "direct main" description: @@ -246,6 +262,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" + url: "https://pub.dev" + source: hosted + version: "2.0.15" flutter_svg: dependency: "direct main" description: @@ -259,6 +283,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" frontend_server_client: dependency: transitive description: @@ -283,6 +312,54 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.0" + google_maps: + dependency: transitive + description: + name: google_maps + sha256: "555d5d736339b0478e821167ac521c810d7b51c3b2734e6802a9f046b64ea37a" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + google_maps_flutter: + dependency: "direct main" + description: + name: google_maps_flutter + sha256: c290921cd1750b5ede99c82dcaa84740da86278e6ed0f83ad29752b29a8552c6 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + google_maps_flutter_android: + dependency: transitive + description: + name: google_maps_flutter_android + sha256: "9512c862df77c1f0fa5f445513dd3c57f5996f0a809dccb74e54b690ee4e3a0f" + url: "https://pub.dev" + source: hosted + version: "2.4.15" + google_maps_flutter_ios: + dependency: transitive + description: + name: google_maps_flutter_ios + sha256: a9462a433bf3ebe60aadcf4906d2d6341a270d69d3e0fcaa8eb2b64699fcfb4f + url: "https://pub.dev" + source: hosted + version: "2.2.3" + google_maps_flutter_platform_interface: + dependency: transitive + description: + name: google_maps_flutter_platform_interface + sha256: b363e9a1ef7d063fb21ec8eef5a450db4b0500cc39712c9410b5cc64013d6fc6 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + google_maps_flutter_web: + dependency: transitive + description: + name: google_maps_flutter_web + sha256: "15303a2ddd04e21ace41c823de8396a61857a61fed4c145f25ca1fc76628c40c" + url: "https://pub.dev" + source: hosted + version: "0.5.2" graphs: dependency: transitive description: @@ -291,6 +368,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" http: dependency: "direct main" description: @@ -331,6 +416,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + js_wrapping: + dependency: transitive + description: + name: js_wrapping + sha256: e385980f7c76a8c1c9a560dfb623b890975841542471eade630b2871d243851c + url: "https://pub.dev" + source: hosted + version: "0.7.4" json_annotation: dependency: transitive description: @@ -539,6 +632,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.3" + sanitize_html: + dependency: transitive + description: + name: sanitize_html + sha256: "0a445f19bbaa196f5a4f93461aa066b94e6e025622eb1e9bc77872a5e25233a5" + url: "https://pub.dev" + source: hosted + version: "2.0.0" shelf: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 32fc873..d977da9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,11 +32,13 @@ dependencies: envied: ^0.3.0+3 flutter: sdk: flutter - provider: flutter_svg: ^2.0.7 google_fonts: ^5.1.0 + google_maps_flutter: ^2.4.0 http: ^1.1.0 + carousel_slider: lottie: ^2.5.0 + provider: null dev_dependencies: build_runner: ^2.4.6 diff --git a/web/index.html b/web/index.html index 6dd4b35..c0fd0c1 100644 --- a/web/index.html +++ b/web/index.html @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - travel_planner_pro - - - - - - - - + + + + + + - + + From b550296344edd99c9c3f25fc1840d8aba5ffc044 Mon Sep 17 00:00:00 2001 From: ch1nru5t Date: Sat, 29 Jul 2023 22:38:47 +0530 Subject: [PATCH 2/3] map working key obfuscated --- lib/env/env.dart | 2 + .../screens/explore_maps_screen.dart | 1 + .../home/screens/mobile_home_screen.dart | 3 +- lib/main.dart | 12 +++- lib/models/user_model.dart | 16 ++--- lib/prefs.dart | 38 ++++++++++++ lib/providers/auth_provider.dart | 3 + lib/router.dart | 18 ++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 60 ++++++++++++++++++- pubspec.yaml | 3 +- web/index.html | 2 +- 12 files changed, 146 insertions(+), 14 deletions(-) create mode 100644 lib/prefs.dart diff --git a/lib/env/env.dart b/lib/env/env.dart index c79dc05..9828a2b 100644 --- a/lib/env/env.dart +++ b/lib/env/env.dart @@ -6,4 +6,6 @@ part 'env.g.dart'; abstract class Env { @EnviedField(varName: 'BASEURL', obfuscate: true) static String baseUrl = _Env.baseUrl; + @EnviedField(varName: 'KEY', obfuscate: true) + static String key = _Env.key; } diff --git a/lib/features/explore_maps/screens/explore_maps_screen.dart b/lib/features/explore_maps/screens/explore_maps_screen.dart index 152eb00..ad95954 100644 --- a/lib/features/explore_maps/screens/explore_maps_screen.dart +++ b/lib/features/explore_maps/screens/explore_maps_screen.dart @@ -104,6 +104,7 @@ class _ExploreMapsScreenState extends State { ), ), Expanded( + flex: 2, child: CarouselSlider.builder( itemCount: locationList!.$2!.length, itemBuilder: (context, index, realIndex) { diff --git a/lib/features/home/screens/mobile_home_screen.dart b/lib/features/home/screens/mobile_home_screen.dart index 9e55e61..d84091a 100644 --- a/lib/features/home/screens/mobile_home_screen.dart +++ b/lib/features/home/screens/mobile_home_screen.dart @@ -74,7 +74,8 @@ class _MobileHomeScreenState extends State { ), ), appBar: AppBar( - title: const Text('Travel Planner'), + centerTitle: true, + title: const Icon(Icons.flight_takeoff_rounded), actions: [ ClipRRect( borderRadius: BorderRadius.circular(20), diff --git a/lib/main.dart b/lib/main.dart index d24278a..0f30126 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,13 +1,19 @@ +import 'dart:html' as html; + import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'package:travel_planner_pro/constants/colors/custom_colors.dart'; +import 'package:travel_planner_pro/env/env.dart'; import 'package:travel_planner_pro/features/landing_page/screens/landing_screen.dart'; +import 'package:travel_planner_pro/prefs.dart'; import 'package:travel_planner_pro/providers/auth_provider.dart'; import 'package:travel_planner_pro/providers/map_provider.dart'; import 'package:travel_planner_pro/router.dart'; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Prefs.init(); runApp( MultiProvider( providers: [ @@ -28,6 +34,10 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { + html.ScriptElement script = html.ScriptElement() + ..src = + 'https://maps.googleapis.com/maps/api/js?key=${Env.key}&libraries=libraries=drawing,visualization,places'; + html.querySelector('#customScript')!.replaceWith(script); return MaterialApp( debugShowCheckedModeBanner: false, title: 'Travel Planner Pro', diff --git a/lib/models/user_model.dart b/lib/models/user_model.dart index 628eaf8..1663c02 100644 --- a/lib/models/user_model.dart +++ b/lib/models/user_model.dart @@ -2,16 +2,16 @@ import 'dart:convert'; class User { String token; - String id; - String userName; - String name; - String email; + String? id; + String? userName; + String? name; + String? email; User({ required this.token, - required this.id, - required this.userName, - required this.name, - required this.email, + this.id, + this.userName, + this.name, + this.email, }); @override diff --git a/lib/prefs.dart b/lib/prefs.dart new file mode 100644 index 0000000..dbc855d --- /dev/null +++ b/lib/prefs.dart @@ -0,0 +1,38 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +class Prefs { + static late SharedPreferences _prefs; + static Future init() async { + _prefs = await SharedPreferences.getInstance(); + return _prefs; + } + + static Future setBool(String key, bool value) async => + await _prefs.setBool(key, value); + + static Future setDouble(String key, double value) async => + await _prefs.setDouble(key, value); + + static Future setInt(String key, int value) async => + await _prefs.setInt(key, value); + + static Future setString(String key, String value) async => + await _prefs.setString(key, value); + + static Future setStringList(String key, List value) async => + await _prefs.setStringList(key, value); + + static bool? getBool(String key) => _prefs.getBool(key); + + static double? getDouble(String key) => _prefs.getDouble(key); + + static int? getInt(String key) => _prefs.getInt(key); + + static String? getString(String key) => _prefs.getString(key); + + static List? getStringList(String key) => _prefs.getStringList(key); + + static Future remove(String key) async => await _prefs.remove(key); + + static Future clear() async => await _prefs.clear(); +} diff --git a/lib/providers/auth_provider.dart b/lib/providers/auth_provider.dart index e531ace..5824911 100644 --- a/lib/providers/auth_provider.dart +++ b/lib/providers/auth_provider.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:travel_planner_pro/features/auth/services/auth_service.dart'; import 'package:travel_planner_pro/features/home/screens/home_screen.dart'; +import 'package:travel_planner_pro/prefs.dart'; import '../models/user_model.dart'; @@ -10,6 +11,7 @@ class AuthProvider extends ChangeNotifier { void clearUser() { user = null; + Prefs.remove('token'); notifyListeners(); } @@ -20,6 +22,7 @@ class AuthProvider extends ChangeNotifier { (String?, User?) data = await authService.login(email.trim(), password); if (data.$1 == null) { user = data.$2; + Prefs.setString('token', user!.token); notifyListeners(); if (context.mounted) { Navigator.pushReplacementNamed( diff --git a/lib/router.dart b/lib/router.dart index a1684fb..9390fdb 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -1,12 +1,30 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:travel_planner_pro/features/home/screens/home_screen.dart'; +import 'package:travel_planner_pro/providers/auth_provider.dart'; import 'features/auth/screens/auth_screen.dart'; import 'features/landing_page/screens/landing_screen.dart'; +import 'models/user_model.dart'; +import 'prefs.dart'; generateRoute(RouteSettings settings) { switch (settings.name) { case AuthScreen.routeName: + if (Prefs.getString('token') != null) { + RouteSettings settings = + const RouteSettings(name: HomeScreen.routeName); + return MaterialPageRoute( + builder: (context) { + context + .read() + .setUser(User(token: Prefs.getString('token')!).copyWith( + token: Prefs.getString('token'), + )); + return const HomeScreen(); + }, + settings: settings); + } if (settings.arguments == null) { RouteSettings settings = const RouteSettings(name: AuthScreen.routeName, arguments: 'login'); diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index e777c67..b8e2b22 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,7 +6,9 @@ import FlutterMacOS import Foundation import path_provider_foundation +import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index beecda0..707a010 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -237,10 +237,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "6.1.4" fixnum: dependency: transitive description: @@ -640,6 +640,62 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4 + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d + url: "https://pub.dev" + source: hosted + version: "2.3.0" shelf: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d977da9..79209a2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,6 +28,7 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: + carousel_slider: null cupertino_icons: ^1.0.2 envied: ^0.3.0+3 flutter: @@ -36,9 +37,9 @@ dependencies: google_fonts: ^5.1.0 google_maps_flutter: ^2.4.0 http: ^1.1.0 - carousel_slider: lottie: ^2.5.0 provider: null + shared_preferences: ^2.2.0 dev_dependencies: build_runner: ^2.4.6 diff --git a/web/index.html b/web/index.html index c0fd0c1..e1ffd82 100644 --- a/web/index.html +++ b/web/index.html @@ -38,7 +38,7 @@ - +