Add Dialog with Pageview to select new house, and then drop a pin where the house is, then zoom map to that area.
This commit is contained in:
BIN
assets/icons/house.png
Normal file
BIN
assets/icons/house.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
3
devtools_options.yaml
Normal file
3
devtools_options.yaml
Normal file
@@ -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:
|
||||
@@ -30,6 +30,8 @@
|
||||
<string>Main</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>This app needs access to location to drop pins</string>
|
||||
<key>GMSApiKey</key>
|
||||
<string>AIzaSyBLSUk32a5qGm3M_n9Yii66I7wi0rmA8oM</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
|
||||
75
lib/chatgpt/test.dart
Normal file
75
lib/chatgpt/test.dart
Normal file
@@ -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<List<Intersection>> 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<Intersection> _parseCsv(String csv) {
|
||||
final lines = LineSplitter().convert(csv.trim());
|
||||
final intersections = <Intersection>[];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
7
lib/common/constants.dart
Normal file
7
lib/common/constants.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Constants {
|
||||
Constants._();
|
||||
static const double padding = 20;
|
||||
static const double avatarRadius = 45;
|
||||
}
|
||||
19
lib/common/functions.dart
Normal file
19
lib/common/functions.dart
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
29
lib/database/schema.dart
Normal file
29
lib/database/schema.dart
Normal file
@@ -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'),
|
||||
]),
|
||||
]));
|
||||
40
lib/dialogs/dialogs.dart
Normal file
40
lib/dialogs/dialogs.dart
Normal file
@@ -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<Dialogs> {
|
||||
@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"),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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<void> main() async {
|
||||
await dotenv.load(fileName: ".env");
|
||||
@@ -88,6 +90,81 @@ class SignMapScreenState extends State<SignMapScreen> {
|
||||
});
|
||||
}
|
||||
|
||||
// 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<Property>(
|
||||
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<SignMapScreen> {
|
||||
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',
|
||||
|
||||
15
lib/models/property.dart
Normal file
15
lib/models/property.dart
Normal file
@@ -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<LatLng> signLocations;
|
||||
|
||||
Property({
|
||||
required this.address,
|
||||
required this.latitude,
|
||||
required this.longitude,
|
||||
required this.signLocations,
|
||||
});
|
||||
}
|
||||
16
lib/screens/list_property/intro_page.dart
Normal file
16
lib/screens/list_property/intro_page.dart
Normal file
@@ -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"))],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
22
lib/screens/list_property/property_address.dart
Normal file
22
lib/screens/list_property/property_address.dart
Normal file
@@ -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"))],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
28
lib/screens/list_property/signs_and_radius.dart
Normal file
28
lib/screens/list_property/signs_and_radius.dart
Normal file
@@ -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")),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
26
lib/screens/list_property/third_page.dart
Normal file
26
lib/screens/list_property/third_page.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget buildThirdPage(
|
||||
TextEditingController signsController,
|
||||
void Function() nextPage,
|
||||
DropdownButtonFormField<String> 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"))],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
88
lib/utilities/google_places_helper.dart
Normal file
88
lib/utilities/google_places_helper.dart
Normal file
@@ -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<AutocompletePrediction>) 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<void> _onAddressChanged({
|
||||
required TextEditingController controller,
|
||||
required Debouncer debouncer,
|
||||
required void Function(List<AutocompletePrediction>) 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<void> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
104
lib/widgets/custom_dialog_box copy.dart
Normal file
104
lib/widgets/custom_dialog_box copy.dart
Normal file
@@ -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<CustomDialogBox> {
|
||||
@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: <Widget>[
|
||||
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: <Widget>[
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
336
lib/widgets/custom_dialog_box.dart
Normal file
336
lib/widgets/custom_dialog_box.dart
Normal file
@@ -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<CustomDialogBox> {
|
||||
final PageController _pageController = PageController();
|
||||
int _currentPage = 0;
|
||||
|
||||
final _addressController = TextEditingController();
|
||||
final _signsController = TextEditingController();
|
||||
String? _selectedRadius;
|
||||
|
||||
final _addressFocusNode = FocusNode();
|
||||
Timer? _debouncer;
|
||||
List<places.AutocompletePrediction> _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<String>(
|
||||
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: <Widget>[
|
||||
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: <Widget>[
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
682
pubspec.lock
682
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"
|
||||
|
||||
11
pubspec.yaml
11
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
|
||||
- assets/icons/sign_marker.png
|
||||
- assets/icons/house.png
|
||||
Reference in New Issue
Block a user