diff --git a/assets/icons/house.png b/assets/icons/house.png new file mode 100644 index 0000000..a536364 Binary files /dev/null and b/assets/icons/house.png differ diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 88a3cfb..d02ae24 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -30,6 +30,8 @@ Main NSLocationWhenInUseUsageDescription This app needs access to location to drop pins + GMSApiKey + AIzaSyBLSUk32a5qGm3M_n9Yii66I7wi0rmA8oM UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/lib/chatgpt/test.dart b/lib/chatgpt/test.dart new file mode 100644 index 0000000..e754d12 --- /dev/null +++ b/lib/chatgpt/test.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +/// Represents a busy intersection. +class Intersection { + final String name; + final double latitude; + final double longitude; + + Intersection(this.name, this.latitude, this.longitude); +} + +/// A service that communicates with the OpenAI ChatGPT API. +class ChatGPTService { + final String apiKey = 'YOUR_API_KEY'; // Replace with your actual API key + final String apiUrl = 'https://api.openai.com/v1/chat/completions'; + + /// Sends a prompt to ChatGPT to find the busiest intersections around the address. + Future> getBusyIntersections({ + required String address, + required int count, + required double radiusMiles, + required String timeOfDay, + }) async { + final prompt = ''' +Given the address "$address", find the $count busiest intersections within $radiusMiles miles during $timeOfDay on a weekday. Return the results in CSV format with columns: intersection_name, latitude, longitude. +'''; + + final response = await http.post( + Uri.parse(apiUrl), + headers: { + 'Authorization': 'Bearer $apiKey', + 'Content-Type': 'application/json', + }, + body: jsonEncode({ + "model": "gpt-4", + "messages": [ + { + "role": "system", + "content": "You are a traffic and mapping expert.", + }, + {"role": "user", "content": prompt}, + ], + }), + ); + + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + final csvString = data['choices'][0]['message']['content']; + return _parseCsv(csvString); + } else { + throw Exception('Failed to get response from ChatGPT: ${response.body}'); + } + } + + /// Parses the CSV response into a list of [Intersection] objects. + List _parseCsv(String csv) { + final lines = LineSplitter().convert(csv.trim()); + final intersections = []; + + for (var i = 1; i < lines.length; i++) { + final parts = lines[i].split(','); + if (parts.length >= 3) { + final name = parts[0].trim(); + final lat = double.tryParse(parts[1].trim()); + final lng = double.tryParse(parts[2].trim()); + if (lat != null && lng != null) { + intersections.add(Intersection(name, lat, lng)); + } + } + } + + return intersections; + } +} diff --git a/lib/common/constants.dart b/lib/common/constants.dart new file mode 100644 index 0000000..de284cf --- /dev/null +++ b/lib/common/constants.dart @@ -0,0 +1,7 @@ +import 'package:flutter/material.dart'; + +class Constants { + Constants._(); + static const double padding = 20; + static const double avatarRadius = 45; +} diff --git a/lib/common/functions.dart b/lib/common/functions.dart new file mode 100644 index 0000000..55ace76 --- /dev/null +++ b/lib/common/functions.dart @@ -0,0 +1,19 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +class Debouncer { + final int milliseconds; + Timer? _timer; + + Debouncer({required this.milliseconds}); + + void run(VoidCallback action) { + _timer?.cancel(); + _timer = Timer(Duration(milliseconds: milliseconds), action); + } + + void dispose() { + _timer?.cancel(); + } +} diff --git a/lib/database/schema.dart b/lib/database/schema.dart new file mode 100644 index 0000000..25615bd --- /dev/null +++ b/lib/database/schema.dart @@ -0,0 +1,29 @@ +import 'package:powersync/powersync.dart'; + +const propertiesTable = 'properties'; +const markersTable = 'markers'; + +Schema schema = Schema(([ + const Table( + propertiesTable, + [ + Column.text('list_id'), + Column.text('photo_id'), + Column.text('created_at'), + Column.text('completed_at'), + Column.text('description'), + Column.integer('completed'), + Column.text('created_by'), + Column.text('completed_by'), + ], + indexes: [ + // Index to allow efficient lookup within a list + Index('list', [IndexedColumn('list_id')]), + ], + ), + const Table('markers', [ + Column.text('created_at'), + Column.text('name'), + Column.text('owner_id'), + ]), +])); diff --git a/lib/dialogs/dialogs.dart b/lib/dialogs/dialogs.dart new file mode 100644 index 0000000..92ffc64 --- /dev/null +++ b/lib/dialogs/dialogs.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:wheres_my_sign/widgets/custom_dialog_box.dart'; + +class Dialogs extends StatefulWidget { + @override + _DialogsState createState() => _DialogsState(); +} + +class _DialogsState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Custom Dialog In Flutter"), + centerTitle: true, + automaticallyImplyLeading: false, + ), + body: Container( + child: Center( + child: ElevatedButton( + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return CustomDialogBox( + title: "Custom Dialog Demo", + descriptions: + "Hii all this is a custom dialog in flutter and you will be use in your flutter applications", + text: "Yes", + ); + }, + ); + }, + child: Text("Custom Dialog"), + ), + ), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index c48e65e..f1228ae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,8 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:geolocator/geolocator.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:wheres_my_sign/models/property.dart'; +import 'package:wheres_my_sign/widgets/custom_dialog_box.dart'; Future main() async { await dotenv.load(fileName: ".env"); @@ -88,6 +90,81 @@ class SignMapScreenState extends State { }); } + // return something like this: + // Property { + // address: "1234 Smith St", + // latitude: 37.7749, + // longitude: -122.4194, + // signLocations: [LatLng(37.77, -122.42), LatLng(37.775, -122.41)], + // } + void _addProperty() async { + final Property? newProperty = await showDialog( + context: context, + builder: (BuildContext context) { + return CustomDialogBox( + title: "Show A Property", + descriptions: "Let's show a new property!", + text: "Yes", + ); + }, + ); + + if (newProperty != null) { + setState(() { + // 🟢 Main property marker + + markers.add( + Marker( + markerId: MarkerId( + 'property_${newProperty.latitude}_${newProperty.longitude}', + ), + position: LatLng(newProperty.latitude, newProperty.longitude), + icon: BitmapDescriptor.defaultMarkerWithHue( + BitmapDescriptor.hueGreen, + ), + infoWindow: InfoWindow(title: newProperty.address), + ), + ); + + // 🔴 Sign location markers + for (int i = 0; i < newProperty.signLocations.length; i++) { + final LatLng signLocation = newProperty.signLocations[i]; + markers.add( + Marker( + markerId: MarkerId('sign_$i'), + position: signLocation, + icon: BitmapDescriptor.defaultMarkerWithHue( + BitmapDescriptor.hueRed, + ), + infoWindow: InfoWindow(title: 'Sign ${i + 1}'), + ), + ); + } + }); + + // Optionally: Move camera to property location + mapController?.animateCamera( + CameraUpdate.newLatLngZoom( + LatLng(newProperty.latitude, newProperty.longitude), + 14.0, + ), + ); + } + } + + // void _addProperty() async { + // showDialog( + // context: context, + // builder: (BuildContext context) { + // return CustomDialogBox( + // title: "Show A Property", + // descriptions: "Let's show a new property!", + // text: "Yes", + // ); + // }, + // ); + // } + void _clearMarkers() { setState(() { markers.clear(); @@ -125,6 +202,13 @@ class SignMapScreenState extends State { floatingActionButton: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ + FloatingActionButton( + onPressed: _addProperty, + backgroundColor: Colors.green, + tooltip: 'Add new property', + child: Icon(Icons.add_home), + ), + SizedBox(height: 12), FloatingActionButton( onPressed: _addMarker, tooltip: 'Drop Pin', diff --git a/lib/models/property.dart b/lib/models/property.dart new file mode 100644 index 0000000..05917aa --- /dev/null +++ b/lib/models/property.dart @@ -0,0 +1,15 @@ +import 'package:google_maps_flutter/google_maps_flutter.dart'; + +class Property { + final String address; + final double latitude; + final double longitude; + final List signLocations; + + Property({ + required this.address, + required this.latitude, + required this.longitude, + required this.signLocations, + }); +} diff --git a/lib/screens/list_property/intro_page.dart b/lib/screens/list_property/intro_page.dart new file mode 100644 index 0000000..22e97cc --- /dev/null +++ b/lib/screens/list_property/intro_page.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +Widget buildFirstPage(void Function() nextPage) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text("Let's add a new property"), + const SizedBox(height: 20), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [TextButton(onPressed: nextPage, child: const Text("Next"))], + ), + ], + ); +} diff --git a/lib/screens/list_property/property_address.dart b/lib/screens/list_property/property_address.dart new file mode 100644 index 0000000..7a6ce26 --- /dev/null +++ b/lib/screens/list_property/property_address.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +Widget buildSecondPage( + TextEditingController addressController, + void Function() nextPage, +) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + controller: addressController, + decoration: const InputDecoration(labelText: 'Property Address'), + ), + const SizedBox(height: 20), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [TextButton(onPressed: nextPage, child: const Text("Next"))], + ), + ], + ); +} diff --git a/lib/screens/list_property/signs_and_radius.dart b/lib/screens/list_property/signs_and_radius.dart new file mode 100644 index 0000000..5199206 --- /dev/null +++ b/lib/screens/list_property/signs_and_radius.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +Widget buildSummaryPage( + TextEditingController addressController, + TextEditingController signsController, + String? selectedRadius, + void Function() nextPage, +) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text("Summary", style: TextStyle(fontWeight: FontWeight.bold)), + const SizedBox(height: 10), + Text("Address: ${addressController.text}"), + Text("Signs: ${signsController.text}"), + Text("Radius: ${selectedRadius ?? 'Not selected'}"), + const SizedBox(height: 20), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton(onPressed: nextPage, child: const Text("Finish")), + ], + ), + ], + ); +} diff --git a/lib/screens/list_property/third_page.dart b/lib/screens/list_property/third_page.dart new file mode 100644 index 0000000..1cc4c2b --- /dev/null +++ b/lib/screens/list_property/third_page.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +Widget buildThirdPage( + TextEditingController signsController, + void Function() nextPage, + DropdownButtonFormField radiusField, +) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + controller: signsController, + decoration: const InputDecoration(labelText: 'Number of Signs'), + keyboardType: TextInputType.number, + ), + const SizedBox(height: 10), + radiusField, + const SizedBox(height: 20), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [TextButton(onPressed: nextPage, child: const Text("Next"))], + ), + ], + ); +} diff --git a/lib/utilities/google_places_helper.dart b/lib/utilities/google_places_helper.dart new file mode 100644 index 0000000..3da579d --- /dev/null +++ b/lib/utilities/google_places_helper.dart @@ -0,0 +1,88 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter_google_places_sdk/flutter_google_places_sdk.dart'; +import 'package:wheres_my_sign/common/functions.dart'; + +class GooglePlacesHelper { + final FlutterGooglePlacesSdk _places; + bool _isHandlingSelection = false; + + GooglePlacesHelper(String apiKey) : _places = FlutterGooglePlacesSdk(apiKey); + + void attachAddressListener({ + required TextEditingController controller, + required FocusNode focusNode, + required void Function(List) onPredictions, + required VoidCallback onOverlayHide, + required Debouncer debouncer, + }) { + controller.addListener(() { + _onAddressChanged( + controller: controller, + debouncer: debouncer, + onPredictions: onPredictions, + onOverlayHide: onOverlayHide, + ); + }); + + focusNode.addListener(() { + if (!focusNode.hasFocus) { + Future.delayed(const Duration(milliseconds: 100), onOverlayHide); + } + }); + } + + Future _onAddressChanged({ + required TextEditingController controller, + required Debouncer debouncer, + required void Function(List) onPredictions, + required VoidCallback onOverlayHide, + }) async { + if (_isHandlingSelection || controller.text.length < 3) return; + + debouncer.run(() async { + try { + final result = await _places.findAutocompletePredictions( + controller.text, + countries: ['us'], + ); + + if (result.predictions.isNotEmpty) { + onPredictions(result.predictions); + } else { + onOverlayHide(); + } + } catch (e) { + debugPrint('Prediction error: $e'); + onOverlayHide(); + } + }); + } + + Future handlePlaceSelection({ + required AutocompletePrediction prediction, + required TextEditingController addressController, + required void Function(double? lat, double? lng) onLatLngRetrieved, + required VoidCallback onOverlayHide, + }) async { + try { + _isHandlingSelection = true; + onOverlayHide(); + + final result = await _places.fetchPlace( + prediction.placeId, + fields: [PlaceField.Address, PlaceField.Location], + ); + + final place = result.place; + if (place != null) { + addressController.text = place.address ?? prediction.fullText; + onLatLngRetrieved(place.latLng?.lat, place.latLng?.lng); + } + } catch (e) { + debugPrint('Place fetch error: $e'); + } finally { + _isHandlingSelection = false; + } + } +} diff --git a/lib/widgets/custom_dialog_box copy.dart b/lib/widgets/custom_dialog_box copy.dart new file mode 100644 index 0000000..416970d --- /dev/null +++ b/lib/widgets/custom_dialog_box copy.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:wheres_my_sign/common/constants.dart'; + +class CustomDialogBox extends StatefulWidget { + final String title, descriptions, text; + final Image? img; + + const CustomDialogBox({ + super.key, + required this.title, + required this.descriptions, + required this.text, + this.img, + }); + + @override + CustomDialogBoxState createState() => CustomDialogBoxState(); +} + +class CustomDialogBoxState extends State { + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(Constants.padding), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context), + ); + } + + contentBox(context) { + return Stack( + children: [ + Container( + padding: EdgeInsets.only( + left: Constants.padding, + top: Constants.avatarRadius + Constants.padding, + right: Constants.padding, + bottom: Constants.padding, + ), + margin: EdgeInsets.only(top: Constants.avatarRadius), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.white, + borderRadius: BorderRadius.circular(Constants.padding), + boxShadow: [ + BoxShadow( + color: Colors.black, + offset: Offset(0, 10), + blurRadius: 10, + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.title, + style: TextStyle(fontSize: 22, fontWeight: FontWeight.w600), + ), + SizedBox(height: 15), + Text( + widget.descriptions, + style: TextStyle(fontSize: 14), + textAlign: TextAlign.center, + ), + SizedBox(height: 22), + Align( + alignment: Alignment.bottomRight, + child: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(widget.text, style: TextStyle(fontSize: 18)), + ), + ), + ], + ), + ), + Positioned( + left: Constants.padding, + right: Constants.padding, + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: Constants.avatarRadius, + child: ClipRRect( + borderRadius: BorderRadius.all( + Radius.circular(Constants.avatarRadius), + ), + child: Image.asset( + "assets/icons/house.png", + width: Constants.avatarRadius * 2, + height: Constants.avatarRadius * 2, + fit: BoxFit.cover, + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/widgets/custom_dialog_box.dart b/lib/widgets/custom_dialog_box.dart new file mode 100644 index 0000000..bfee2e5 --- /dev/null +++ b/lib/widgets/custom_dialog_box.dart @@ -0,0 +1,336 @@ +import 'package:flutter/material.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart' as gmaps; +import 'package:flutter_google_places_sdk/flutter_google_places_sdk.dart' + as places; +import 'package:wheres_my_sign/common/constants.dart'; +import 'package:smooth_page_indicator/smooth_page_indicator.dart'; +import 'dart:async'; + +import 'package:wheres_my_sign/models/property.dart'; + +class CustomDialogBox extends StatefulWidget { + final String title, descriptions, text; + final Image? img; + + const CustomDialogBox({ + super.key, + required this.title, + required this.descriptions, + required this.text, + this.img, + }); + + @override + CustomDialogBoxState createState() => CustomDialogBoxState(); +} + +class CustomDialogBoxState extends State { + final PageController _pageController = PageController(); + int _currentPage = 0; + + final _addressController = TextEditingController(); + final _signsController = TextEditingController(); + String? _selectedRadius; + + final _addressFocusNode = FocusNode(); + Timer? _debouncer; + List _predictions = []; + + final places.FlutterGooglePlacesSdk _places = places.FlutterGooglePlacesSdk( + 'AIzaSyBLSUk32a5qGm3M_n9Yii66I7wi0rmA8oM', + ); + + late Property property; // Declare property to store final details + + @override + void dispose() { + _addressController.dispose(); + _signsController.dispose(); + _debouncer?.cancel(); + super.dispose(); + } + + void _onAddressChanged(String value) { + if (_debouncer?.isActive ?? false) _debouncer!.cancel(); + _debouncer = Timer(const Duration(milliseconds: 300), () async { + if (value.isNotEmpty) { + final result = await _places.findAutocompletePredictions(value); + setState(() => _predictions = result.predictions); + } else { + setState(() => _predictions = []); + } + }); + } + + void _selectPrediction(places.AutocompletePrediction prediction) async { + // Fetch place details + final placeDetails = await _places.fetchPlace( + prediction.placeId, + fields: [ + places.PlaceField.Location, + places.PlaceField.AddressComponents, + places.PlaceField.Name, + ], + ); + + final place = placeDetails.place; + + // Null checks for place and latLng + if (place != null && place.latLng != null) { + final latLng = + place + .latLng!; // Use the null check operator, since we've already verified it's not null + + setState(() { + _addressController.text = prediction.fullText; + _predictions = []; + property = Property( + latitude: latLng.lat, + longitude: latLng.lng, + address: + place.name ?? 'Unknown', // Default to 'Unknown' if name is null + signLocations: [], + ); + }); + } + + FocusScope.of(context).unfocus(); // Close keyboard + } + + void _nextPage() { + if (_currentPage < 3) { + setState(() => _currentPage++); + _pageController.animateToPage( + _currentPage, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + } + + void _previousPage() { + if (_currentPage > 0) { + setState(() => _currentPage--); + _pageController.animateToPage( + _currentPage, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + } + + Widget _buildNavigationButtons() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (_currentPage > 0) + TextButton(onPressed: _previousPage, child: const Text("Previous")), + const Spacer(), + if (_currentPage < 3) + TextButton(onPressed: _nextPage, child: const Text("Next")) + else + TextButton( + onPressed: () { + Navigator.of(context).pop(property); + }, + child: const Text("Show"), + ), + ], + ); + } + + Widget _buildPageContent() { + return SizedBox( + height: MediaQuery.of(context).size.height * 0.25, + child: PageView( + controller: _pageController, + physics: const NeverScrollableScrollPhysics(), + children: [ + // Page 1 + Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + "Let's show a property. Over the next few pages, we'll ask for the address, how many signs you want to place, and the radius you'd like to reach. The final page will confirm your input and show the best locations for your open house signs. Ready? Let's Begin!", + textAlign: TextAlign.justify, + ), + const SizedBox(height: 20), + const Spacer(), + _buildNavigationButtons(), + ], + ), + + // Page 2 - Address with Autocomplete + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextFormField( + controller: _addressController, + focusNode: _addressFocusNode, + onChanged: _onAddressChanged, + decoration: const InputDecoration( + labelText: 'Property Address', + ), + ), + if (_predictions.isNotEmpty) + Container( + height: 150, + child: ListView.builder( + itemCount: _predictions.length, + itemBuilder: (context, index) { + final p = _predictions[index]; + return ListTile( + title: Text(p.fullText), + onTap: () => _selectPrediction(p), + ); + }, + ), + ), + const SizedBox(height: 20), + Spacer(), + _buildNavigationButtons(), + ], + ), + + // Page 3 + Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + controller: _signsController, + decoration: const InputDecoration(labelText: 'Number of Signs'), + keyboardType: TextInputType.number, + ), + const SizedBox(height: 10), + DropdownButtonFormField( + value: _selectedRadius, + decoration: const InputDecoration(labelText: 'Search Radius'), + items: + ['1 mile', '2 miles', '5 miles'] + .map((e) => DropdownMenuItem(value: e, child: Text(e))) + .toList(), + onChanged: (val) => setState(() => _selectedRadius = val), + ), + const SizedBox(height: 20), + const Spacer(), + _buildNavigationButtons(), + ], + ), + + // Page 4 - Summary + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "Summary", + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Text("Address: ${_addressController.text}"), + Text("Signs: ${_signsController.text}"), + Text("Radius: ${_selectedRadius ?? 'Not selected'}"), + const SizedBox(height: 20), + const Spacer(), + _buildNavigationButtons(), + ], + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(Constants.padding), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context), + ); + } + + Widget contentBox(BuildContext context) { + return Stack( + children: [ + Container( + padding: EdgeInsets.only( + left: Constants.padding, + top: Constants.avatarRadius + Constants.padding, + right: Constants.padding, + bottom: Constants.padding, + ), + margin: EdgeInsets.only(top: Constants.avatarRadius), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.white, + borderRadius: BorderRadius.circular(Constants.padding), + boxShadow: const [ + BoxShadow( + color: Colors.black, + offset: Offset(0, 10), + blurRadius: 10, + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.title, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 15), + Text( + widget.descriptions, + style: const TextStyle(fontSize: 14), + textAlign: TextAlign.center, + ), + const SizedBox(height: 15), + SmoothPageIndicator( + controller: _pageController, + count: 4, + effect: WormEffect( + dotHeight: 10, + dotWidth: 10, + spacing: 8, + activeDotColor: Theme.of(context).primaryColor, + dotColor: Colors.grey.shade300, + ), + ), + const SizedBox(height: 15), + _buildPageContent(), + ], + ), + ), + Positioned( + left: Constants.padding, + right: Constants.padding, + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: Constants.avatarRadius, + child: ClipRRect( + borderRadius: const BorderRadius.all( + Radius.circular(Constants.avatarRadius), + ), + child: + widget.img ?? + Image.asset( + "assets/icons/house.png", + width: Constants.avatarRadius * 2, + height: Constants.avatarRadius * 2, + fit: BoxFit.cover, + ), + ), + ), + ), + ], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 3cfa83f..1f3d21e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,46 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + app_links: + dependency: transitive + description: + name: app_links + sha256: "85ed8fc1d25a76475914fff28cc994653bd900bc2c26e4b57a49e097febb54ba" + url: "https://pub.dev" + source: hosted + version: "6.4.0" + app_links_linux: + dependency: transitive + description: + name: app_links_linux + sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + app_links_platform_interface: + dependency: transitive + description: + name: app_links_platform_interface + sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + app_links_web: + dependency: transitive + description: + name: app_links_web + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" async: dependency: transitive description: @@ -25,6 +65,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" clock: dependency: transitive description: @@ -73,6 +121,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + fetch_api: + dependency: transitive + description: + name: fetch_api + sha256: "5198267e748828e3ac6199b7394dc60abba43ad8f6dd203e5351bd7bf3fd9efb" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + fetch_client: + dependency: transitive + description: + name: fetch_client + sha256: ac87abcf7f71b509b1619b5cae7d23e4abd3912e2c17e542fdee9eac28e6829e + url: "https://pub.dev" + source: hosted + version: "1.1.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" fixnum: dependency: transitive description: @@ -94,6 +174,78 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.1" + flutter_google_places_sdk: + dependency: "direct main" + description: + name: flutter_google_places_sdk + sha256: "707d9729960bb50fb38fbaa407ad78fa9fd31e4faac1e319d5e8cc3c3c7db584" + url: "https://pub.dev" + source: hosted + version: "0.4.2+1" + flutter_google_places_sdk_android: + dependency: transitive + description: + name: flutter_google_places_sdk_android + sha256: "48cdb684af36a6fcf26425035a5a2f5858ee36ae9c2a003886d60d34c672554f" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + flutter_google_places_sdk_http: + dependency: transitive + description: + name: flutter_google_places_sdk_http + sha256: "5352e657ef0e55e3ba0011463847c7c0c37899591493ce3b12542524ec78a643" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + flutter_google_places_sdk_ios: + dependency: transitive + description: + name: flutter_google_places_sdk_ios + sha256: "8834ad1e2083589604e52680a54d3695ad8cf409c6ae9e8636ae451256d86af7" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + flutter_google_places_sdk_linux: + dependency: transitive + description: + name: flutter_google_places_sdk_linux + sha256: "06bcbe1c654db1720008309e902edf0b798aa205391d6fe29d228490029bbc15" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + flutter_google_places_sdk_macos: + dependency: transitive + description: + name: flutter_google_places_sdk_macos + sha256: "9958383862da2ca01114701f3e89de839951ab17e13401f1a5bc95370882f16c" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + flutter_google_places_sdk_platform_interface: + dependency: transitive + description: + name: flutter_google_places_sdk_platform_interface + sha256: d0a3cbce611c98ace16c847cdac586c21751205c83d0b46de0d5821ac3d37ea3 + url: "https://pub.dev" + source: hosted + version: "0.3.2+1" + flutter_google_places_sdk_web: + dependency: transitive + description: + name: flutter_google_places_sdk_web + sha256: f73fff5285e60aaed9a0a26f74dd31e4077c278694a9a76dae212fb68944daa7 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + flutter_google_places_sdk_windows: + dependency: transitive + description: + name: flutter_google_places_sdk_windows + sha256: "9540cb5877993fa2ea766003dda5280be2c0f37ea2e5ccba0bb14c32d57efe89" + url: "https://pub.dev" + source: hosted + version: "0.2.1" flutter_lints: dependency: "direct dev" description: @@ -106,10 +258,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "5a1e6fb2c0561958d7e4c33574674bda7b77caaca7a33b758876956f2902eea3" + sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.0.28" flutter_test: dependency: "direct dev" description: flutter @@ -120,6 +272,22 @@ packages: description: flutter source: sdk version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: c87ff004c8aa6af2d531668b46a4ea379f7191dc6dfa066acd53d506da6e044b + url: "https://pub.dev" + source: hosted + version: "3.0.0" + functions_client: + dependency: transitive + description: + name: functions_client + sha256: a49876ebae32a50eb62483c5c5ac80ed0d8da34f98ccc23986b03a8d28cee07c + url: "https://pub.dev" + source: hosted + version: "2.4.1" geolocator: dependency: "direct main" description: @@ -168,6 +336,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.5" + go_router: + dependency: "direct main" + description: + name: go_router + sha256: "4cdfcc6a178632d1dbb7a728f8e84a1466211354704b9cdc03eee661d3277732" + url: "https://pub.dev" + source: hosted + version: "15.0.0" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "55580f436822d64c8ff9a77e37d61f5fb1e6c7ec9d632a43ee324e2a05c3c6c9" + url: "https://pub.dev" + source: hosted + version: "0.3.3" google_maps: dependency: transitive description: @@ -188,10 +372,10 @@ packages: dependency: transitive description: name: google_maps_flutter_android - sha256: "0ede4ae8326335c0c007c8c7a8c9737449263123385e2bdf49f3e71103b2dc2e" + sha256: ab83128296fbeaa52e8f2b3bf53bcd895e64778edddcdc07bc8f33f4ea78076c url: "https://pub.dev" source: hosted - version: "2.16.0" + version: "2.16.1" google_maps_flutter_ios: dependency: transitive description: @@ -216,6 +400,62 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.12" + google_sign_in: + dependency: "direct main" + description: + name: google_sign_in + sha256: d0a2c3bcb06e607bb11e4daca48bd4b6120f0bbc4015ccebbe757d24ea60ed2a + url: "https://pub.dev" + source: hosted + version: "6.3.0" + google_sign_in_android: + dependency: transitive + description: + name: google_sign_in_android + sha256: d5e23c56a4b84b6427552f1cf3f98f716db3b1d1a647f16b96dbb5b93afa2805 + url: "https://pub.dev" + source: hosted + version: "6.2.1" + google_sign_in_ios: + dependency: transitive + description: + name: google_sign_in_ios + sha256: "102005f498ce18442e7158f6791033bbc15ad2dcc0afa4cf4752e2722a516c96" + url: "https://pub.dev" + source: hosted + version: "5.9.0" + google_sign_in_platform_interface: + dependency: transitive + description: + name: google_sign_in_platform_interface + sha256: "5f6f79cf139c197261adb6ac024577518ae48fdff8e53205c5373b5f6430a8aa" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + google_sign_in_web: + dependency: transitive + description: + name: google_sign_in_web + sha256: "460547beb4962b7623ac0fb8122d6b8268c951cf0b646dd150d60498430e4ded" + url: "https://pub.dev" + source: hosted + version: "0.12.4+4" + gotrue: + dependency: transitive + description: + name: gotrue + sha256: d6362dff9a54f8c1c372bb137c858b4024c16407324d34e6473e59623c9b9f50 + url: "https://pub.dev" + source: hosted + version: "2.11.1" + gtk: + dependency: transitive + description: + name: gtk + sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c + url: "https://pub.dev" + source: hosted + version: "2.1.0" html: dependency: transitive description: @@ -224,6 +464,54 @@ packages: url: "https://pub.dev" source: hosted version: "0.15.5+1" + http: + dependency: transitive + description: + name: http + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f + url: "https://pub.dev" + source: hosted + version: "1.3.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + intl: + dependency: transitive + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + jwt_decode: + dependency: transitive + description: + name: jwt_decode + sha256: d2e9f68c052b2225130977429d30f187aa1981d789c76ad104a32243cfdebfbb + url: "https://pub.dev" + source: hosted + version: "0.3.1" + latlong2: + dependency: transitive + description: + name: latlong2 + sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe" + url: "https://pub.dev" + source: hosted + version: "0.9.1" leak_tracker: dependency: transitive description: @@ -256,6 +544,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" matcher: dependency: transitive description: @@ -280,6 +576,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mutex: + dependency: transitive + description: + name: mutex + sha256: "8827da25de792088eb33e572115a5eb0d61d61a3c01acbc8bcbe76ed78f1a1f2" + url: "https://pub.dev" + source: hosted + version: "3.1.0" path: dependency: transitive description: @@ -288,6 +600,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + url: "https://pub.dev" + source: hosted + version: "2.2.17" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" permission_handler: dependency: "direct main" description: @@ -336,6 +696,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.1" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -344,6 +712,78 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + postgrest: + dependency: transitive + description: + name: postgrest + sha256: b74dc0f57b5dca5ce9f57a54b08110bf41d6fc8a0483c0fec10c79e9aa0fb2bb + url: "https://pub.dev" + source: hosted + version: "2.4.1" + powersync: + dependency: "direct main" + description: + name: powersync + sha256: "7568576ae8b9cb15049b8fdc2f19c3c8894bbb9609183878b2fe9ad7ad486a28" + url: "https://pub.dev" + source: hosted + version: "1.12.2" + powersync_core: + dependency: transitive + description: + name: powersync_core + sha256: "4f6b89ea4c9be03a967ca3c3a16c3c20d8fda9e69314e5f5a1c5fdd2640fd8bf" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + powersync_flutter_libs: + dependency: transitive + description: + name: powersync_flutter_libs + sha256: b3f0bdebec683670875cb0233111cd93d4dcef11b5d67449f7a5695eb4353ff2 + url: "https://pub.dev" + source: hosted + version: "0.4.7" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + realtime_client: + dependency: transitive + description: + name: realtime_client + sha256: e3089dac2121917cc0c72d42ab056fea0abbaf3c2229048fc50e64bafc731adf + url: "https://pub.dev" + source: hosted + version: "2.4.2" + retry: + dependency: transitive + description: + name: retry + sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" sanitize_html: dependency: transitive description: @@ -352,11 +792,75 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + shared_preferences: + dependency: transitive + description: + name: shared_preferences + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + url: "https://pub.dev" + source: hosted + version: "2.4.10" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.0" + smooth_page_indicator: + dependency: "direct main" + description: + name: smooth_page_indicator + sha256: b21ebb8bc39cf72d11c7cfd809162a48c3800668ced1c9da3aade13a32cf6c1c + url: "https://pub.dev" + source: hosted + version: "1.2.1" source_span: dependency: transitive description: @@ -373,6 +877,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: "310af39c40dd0bb2058538333c9d9840a2725ae0b9f77e4fd09ad6696aa8f66e" + url: "https://pub.dev" + source: hosted + version: "2.7.5" + sqlite3_flutter_libs: + dependency: transitive + description: + name: sqlite3_flutter_libs + sha256: "1a96b59227828d9eb1463191d684b37a27d66ee5ed7597fcf42eee6452c88a14" + url: "https://pub.dev" + source: hosted + version: "0.5.32" + sqlite3_web: + dependency: transitive + description: + name: sqlite3_web + sha256: "967e076442f7e1233bd7241ca61f3efe4c7fc168dac0f38411bdb3bdf471eb3c" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + sqlite_async: + dependency: transitive + description: + name: sqlite_async + sha256: a60e8d5c8df8e694933bd5a312c38393e79ad77d784bb91c6f38ba627bfb7aec + url: "https://pub.dev" + source: hosted + version: "0.11.4" stack_trace: dependency: transitive description: @@ -381,6 +917,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.1" + storage_client: + dependency: transitive + description: + name: storage_client + sha256: "9f9ed283943313b23a1b27139bb18986e9b152a6d34530232c702c468d98e91a" + url: "https://pub.dev" + source: hosted + version: "2.3.1" stream_channel: dependency: transitive description: @@ -405,6 +949,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + supabase: + dependency: transitive + description: + name: supabase + sha256: c3ebddba69ddcf16d8b78e8c44c4538b0193d1cf944fde3b72eb5b279892a370 + url: "https://pub.dev" + source: hosted + version: "2.6.3" + supabase_flutter: + dependency: "direct main" + description: + name: supabase_flutter + sha256: "3b5b5b492e342f63f301605d0c66f6528add285b5744f53c9fd9abd5ffdbce5b" + url: "https://pub.dev" + source: hosted + version: "2.8.4" term_glyph: dependency: transitive description: @@ -429,8 +989,80 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" - uuid: + universal_io: dependency: transitive + description: + name: universal_io + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + url_launcher: + dependency: transitive + description: + name: url_launcher + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79" + url: "https://pub.dev" + source: hosted + version: "6.3.16" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" + url: "https://pub.dev" + source: hosted + version: "6.3.3" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + uuid: + dependency: "direct main" description: name: uuid sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff @@ -461,6 +1093,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: bfe6f435f6ec49cb6c01da1e275ae4228719e59a6b067048c51e72d9d63bcc4b + url: "https://pub.dev" + source: hosted + version: "1.0.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" + yet_another_json_isolate: + dependency: transitive + description: + name: yet_another_json_isolate + sha256: "56155e9e0002cc51ea7112857bbcdc714d4c35e176d43e4d3ee233009ff410c9" + url: "https://pub.dev" + source: hosted + version: "2.0.3" sdks: dart: ">=3.7.2 <4.0.0" flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index 70b79cf..4d0fba8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,13 @@ dependencies: geolocator: ^14.0.0 permission_handler: ^12.0.0+1 flutter_dotenv: ^5.2.1 + powersync: ^1.12.2 + uuid: ^4.5.1 + supabase_flutter: ^2.8.4 + google_sign_in: ^6.3.0 + go_router: ^15.0.0 + smooth_page_indicator: ^1.2.1 + flutter_google_places_sdk: ^0.4.2+1 dev_dependencies: flutter_test: @@ -93,5 +100,7 @@ flutter: # see https://flutter.dev/to/font-from-package assets: - .env + - assets/ - assets/app_title.png - - assets/icons/sign_marker.png \ No newline at end of file + - assets/icons/sign_marker.png + - assets/icons/house.png \ No newline at end of file