forked from eatvio/eatvio_app
feat(registration): add location by coordinates
This commit is contained in:
@@ -1,13 +1,9 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.eatvioapp.app">
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
|
||||
|
||||
<application
|
||||
android:label="Eatvio"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ pluginManagement {
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "7.3.0" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
|
||||
id "com.android.application" version "7.3.1" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.9.10" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
|
||||
@@ -57,5 +57,7 @@
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -64,4 +64,14 @@ class RegistrationCubit extends Cubit<RegistrationState> {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<String>> getLocationsByCoordinates(String latitude, String longitude) async {
|
||||
try {
|
||||
final location = (await registrationRepository.getLocationsListByCoordinates(latitude, longitude));
|
||||
emit(RegistrationState(sheet: state.sheet.copyWith(responseBody: location.responseBody)));
|
||||
return location.locations;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@ import 'package:eatvio_app/core/app_export.dart';
|
||||
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
|
||||
import 'package:eatvio_app/features/registration/presentation/bloc/registration_cubit/registration_cubit.dart';
|
||||
import 'package:eatvio_app/widgets/custom_edit_text_form_field.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:location/location.dart';
|
||||
|
||||
class CityOfLivingScreen extends StatefulWidget {
|
||||
final UserRegistrationSheet sheet;
|
||||
@@ -21,6 +23,8 @@ class _CityOfLivingScreenState extends State<CityOfLivingScreen> {
|
||||
|
||||
late SelectionPopupModel selectedItem;
|
||||
final cityController = TextEditingController();
|
||||
final suggestionsController = SuggestionsController<String>();
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -30,6 +34,34 @@ class _CityOfLivingScreenState extends State<CityOfLivingScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<LocationData?> getLocationData() async {
|
||||
Location location = new Location();
|
||||
|
||||
bool _serviceEnabled;
|
||||
PermissionStatus _permissionGranted;
|
||||
LocationData _locationData;
|
||||
|
||||
_serviceEnabled = await location.serviceEnabled();
|
||||
if (!_serviceEnabled) {
|
||||
_serviceEnabled = await location.requestService();
|
||||
if (!_serviceEnabled) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
_permissionGranted = await location.hasPermission();
|
||||
if (_permissionGranted == PermissionStatus.denied) {
|
||||
_permissionGranted = await location.requestPermission();
|
||||
if (_permissionGranted != PermissionStatus.granted) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
_locationData = await location.getLocation();
|
||||
|
||||
return _locationData;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
@@ -39,43 +71,89 @@ class _CityOfLivingScreenState extends State<CityOfLivingScreen> {
|
||||
children: [
|
||||
Text("Местоположение"),
|
||||
SizedBox(height: 4),
|
||||
TypeAheadField(
|
||||
debounceDuration: Duration(milliseconds: 300),
|
||||
controller: cityController,
|
||||
builder: (context, controller, focus) => CustomTextFormField(
|
||||
controller: cityController,
|
||||
focusNode: focus,
|
||||
autofocus: true,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.black,
|
||||
)),
|
||||
itemBuilder: (BuildContext context, String item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(item, style: theme.textTheme.bodyLarge?.copyWith(color: Colors.black)),
|
||||
);
|
||||
},
|
||||
decorationBuilder: (context, child) => Material(
|
||||
type: MaterialType.card,
|
||||
elevation: 4,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: child,
|
||||
),
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
cityController.text = item;
|
||||
});
|
||||
final registrationCubit = context.read<RegistrationCubit>();
|
||||
registrationCubit.updateSheet(registrationCubit.state.sheet.copyWith(location: item));
|
||||
},
|
||||
suggestionsCallback: (query) async {
|
||||
if (query.length >= 3) {
|
||||
final registrationCubit = context.read<RegistrationCubit>();
|
||||
return (await registrationCubit.getLocationsByQuery(query));
|
||||
}
|
||||
return null;
|
||||
},
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width - 80,
|
||||
child: TypeAheadField(
|
||||
debounceDuration: Duration(milliseconds: 300),
|
||||
controller: cityController,
|
||||
suggestionsController: suggestionsController,
|
||||
builder: (context, controller, focus) => CustomTextFormField(
|
||||
controller: cityController,
|
||||
focusNode: focus,
|
||||
autofocus: true,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.black,
|
||||
)),
|
||||
itemBuilder: (BuildContext context, String item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(item, style: theme.textTheme.bodyLarge?.copyWith(color: Colors.black)),
|
||||
);
|
||||
},
|
||||
decorationBuilder: (context, child) => Material(
|
||||
type: MaterialType.card,
|
||||
elevation: 4,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: child,
|
||||
),
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
cityController.text = item;
|
||||
});
|
||||
final registrationCubit = context.read<RegistrationCubit>();
|
||||
registrationCubit.updateSheet(registrationCubit.state.sheet.copyWith(location: item));
|
||||
},
|
||||
suggestionsCallback: (query) async {
|
||||
if (query.length >= 3) {
|
||||
final registrationCubit = context.read<RegistrationCubit>();
|
||||
return (await registrationCubit.getLocationsByQuery(query));
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
InkWell(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
onTap: !isLoading
|
||||
? () async {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
final LocationData? locationData = await getLocationData();
|
||||
if (locationData != null) {
|
||||
final List<String> locations = await context
|
||||
.read<RegistrationCubit>()
|
||||
.getLocationsByCoordinates(locationData.latitude.toString(), locationData.longitude.toString());
|
||||
setState(() {
|
||||
cityController.text = locations.first;
|
||||
suggestionsController.suggestions = locations;
|
||||
});
|
||||
}
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
: null,
|
||||
child: Ink(
|
||||
height: 40,
|
||||
width: 40,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Color(0xFFEAF2FD),
|
||||
),
|
||||
child: !isLoading
|
||||
? Icon(
|
||||
Icons.near_me_rounded,
|
||||
color: appTheme.blueA400,
|
||||
)
|
||||
: CupertinoActivityIndicator(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -22,4 +22,12 @@ class RegistrationRepository {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<LocationModel> getLocationsListByCoordinates(String latitude, String longitude) async {
|
||||
try {
|
||||
return (await registrationService.getLocationsByCoordinate(latitude: latitude, longitude: longitude));
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ abstract class RegistrationService {
|
||||
@Query('user_address') required String query,
|
||||
});
|
||||
|
||||
@GET('/api/api/location_by_coordinate')
|
||||
@GET('/api/location_by_coordinate')
|
||||
Future<LocationModel> getLocationsByCoordinate({
|
||||
@Query('coordinate[position][latitude]') required String latitude,
|
||||
@Query('coordinate[position][longitude]') required String longitude,
|
||||
|
||||
@@ -94,7 +94,7 @@ class _RegistrationService implements RegistrationService {
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/api/location_by_coordinate',
|
||||
'/api/location_by_coordinate',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
|
||||
@@ -44,6 +44,7 @@ dependencies:
|
||||
lazy_load_scrollview: ^1.3.0
|
||||
badges: ^3.1.2
|
||||
google_fonts: ^6.2.1
|
||||
location: ^7.0.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.11
|
||||
|
||||
Reference in New Issue
Block a user