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