This commit is contained in:
Juan Felipe Duarte
2023-04-22 14:33:53 -05:00
parent f702d4e0e6
commit 03bd8401b5
12 changed files with 642 additions and 216 deletions
+11 -1
View File
@@ -6,6 +6,7 @@ import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/models/user_model.dart';
import 'package:prosappco/src/screens/calendar.dart';
import 'package:prosappco/src/screens/profile.dart';
class DrawerProfessional extends StatefulWidget {
@@ -155,7 +156,16 @@ class _DrawerProfessionalState extends State<DrawerProfessional> {
),
),
ListTile(
onTap: () {},
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return const CalendarScreen();
},
),
);
},
leading: const Icon(
Icons.calendar_month,
color: Colors.black,
+16
View File
@@ -0,0 +1,16 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart';
final uid = AuthenticationRepository.instance.getCurrentUserUid();
// class EventoService {
// Future<Event> createEvent() {
// FirebaseFirestore.instance.collection('users').doc(uid).update({
// 'ejemplo': 'ejm',
// });
// try {} catch (e) {
// print('Evento $e');
// }
// }
// }
+78
View File
@@ -0,0 +1,78 @@
import 'package:flutter/material.dart';
import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:table_calendar/table_calendar.dart';
class CalendarScreen extends StatefulWidget {
const CalendarScreen({super.key});
@override
State<CalendarScreen> createState() => _CalendarScreenState();
}
class _CalendarScreenState extends State<CalendarScreen> {
CalendarFormat _calendarFormat = CalendarFormat.month;
DateTime today = DateTime.now();
@override
void initState() {
super.initState();
}
void _onDaySelected(DateTime day, DateTime focusedDay) {
setState(() {
today = day;
});
}
void _onFormatChange(CalendarFormat format) {
setState(() {
_calendarFormat = format;
});
}
@override
Widget build(BuildContext context) {
// DateTime firstDay = today.subtract(Duration(days: 365));
DateTime lastDay = today.add(const Duration(days: 365));
return SafeArea(
child: Scaffold(
appBar: PopAppbar(
onPressed: () {
Navigator.pop(context);
},
label: 'Calendario',
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
color: const Color.fromARGB(255, 224, 247, 255),
child: TableCalendar(
locale: 'es_MX',
firstDay: DateTime.utc(2010, 10, 16),
lastDay: lastDay,
focusedDay: today,
availableGestures: AvailableGestures.all,
onDaySelected: _onDaySelected,
selectedDayPredicate: (day) => isSameDay(day, today),
calendarFormat: _calendarFormat,
onFormatChanged: _onFormatChange,
availableCalendarFormats: const {
CalendarFormat.month: 'Mes',
CalendarFormat.week: 'Semana',
CalendarFormat.twoWeeks: '2 Semanas',
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
),
);
}
}
+18 -17
View File
@@ -60,7 +60,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
child: Row(
children: <Widget>[
IconButton(
icon: Icon(
icon: const Icon(
Icons.arrow_back,
size: 30,
),
@@ -68,7 +68,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
Navigator.pop(context);
},
),
Text(
const Text(
'Registro',
style: TextStyle(
color: Color(0xFF262626),
@@ -86,23 +86,23 @@ class _RegisterScreenState extends State<RegisterScreen> {
margin: const EdgeInsets.only(top: 200, left: 50, right: 50),
child: Column(children: [
Padding(
padding: EdgeInsets.only(bottom: 20),
padding: const EdgeInsets.only(bottom: 20),
child: ElevatedButton(
onPressed: () async {
await AuthenticationRepository.instance
.signInWithGoogle();
},
style: ElevatedButton.styleFrom(
primary: Color(0xFF2BA4EC),
backgroundColor: const Color(0xFF2BA4EC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
elevation: 0,
minimumSize: Size(230, 60),
minimumSize: const Size(230, 60),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
children: const [
Text(
'Entrar con Google ',
style: TextStyle(
@@ -117,9 +117,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
)),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 0),
padding: const EdgeInsets.symmetric(vertical: 0),
child: Row(
children: <Widget>[
children: const <Widget>[
Expanded(
child: Divider(
color: Colors.black38,
@@ -153,10 +153,10 @@ class _RegisterScreenState extends State<RegisterScreen> {
color: Color(0xFF65676B))),
)),
Padding(
padding: EdgeInsets.only(bottom: 18),
padding: const EdgeInsets.only(bottom: 18),
child: TextFormField(
controller: controller.email,
decoration: InputDecoration(
decoration: const InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Color(0xFFECECEC)),
@@ -190,22 +190,23 @@ class _RegisterScreenState extends State<RegisterScreen> {
controller: controller.password,
obscureText: _obscureText,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
enabledBorder: const OutlineInputBorder(
borderSide:
BorderSide(color: Color(0xFFECECEC)),
borderRadius: BorderRadius.all(
Radius.circular(50),
)),
focusedBorder: OutlineInputBorder(
focusedBorder: const OutlineInputBorder(
borderSide:
BorderSide(color: Color(0xFFECECEC)),
borderRadius: BorderRadius.all(
Radius.circular(50),
)),
hintText: 'Contraseña',
fillColor: Color.fromARGB(255, 239, 239, 239),
fillColor:
const Color.fromARGB(255, 239, 239, 239),
filled: true,
prefixIcon: Icon(Icons.lock_outline),
prefixIcon: const Icon(Icons.lock_outline),
suffixIcon: IconButton(
icon: Icon(
_obscureText
@@ -242,19 +243,19 @@ class _RegisterScreenState extends State<RegisterScreen> {
),
RichText(
text: TextSpan(
style: TextStyle(
style: const TextStyle(
fontSize: 16.0,
color: Color(0xFF65676B),
fontFamily: 'Poppins',
),
children: [
TextSpan(text: 'Ya estas registrado? '),
const TextSpan(text: 'Ya estas registrado? '),
WidgetSpan(
child: GestureDetector(
onTap: () {
Navigator.pushReplacementNamed(context, '/login');
},
child: Text(
child: const Text(
'Iniciar Sesión',
style: TextStyle(
fontSize: 16.0,
+347 -183
View File
@@ -1,10 +1,15 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'dart:async';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/drawer_menu.dart';
import 'package:prosappco/src/models/score_model.dart';
import 'package:prosappco/src/screens/professional.dart';
import 'package:intl/intl.dart';
@@ -16,12 +21,53 @@ class ServiceScreen extends StatefulWidget {
}
class _ServiceScreenState extends State<ServiceScreen> {
final TextEditingController _locationController = TextEditingController();
final String _locationPosition = '';
final DateFormat formatter = DateFormat('dd/MM/yyyy');
final DateTime now = DateTime.now();
DateTime? _selectedDate;
TimeOfDay? _selectedTime;
late GoogleMapController googleMapController;
static const CameraPosition initialCameraPosition = CameraPosition(
target: LatLng(7.8939100, -72.5078200),
zoom: 14.4746,
);
Set<Marker> markers = {};
Future<Position> _determinePosition() async {
bool serviceEnabled;
LocationPermission permission;
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
return Future.error('Location services are disabled');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
return Future.error('Location permission denied');
}
}
if (permission == LocationPermission.deniedForever) {
return Future.error('Location permissions are permanently denied');
}
Position position = await Geolocator.getCurrentPosition();
return position;
}
Future<void> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
@@ -63,6 +109,25 @@ class _ServiceScreenState extends State<ServiceScreen> {
super.initState();
}
late String lat;
late String long;
var coordinates;
Future<String> getLocationName(double latitude, double longitude) async {
String address;
List<Placemark> placemarks =
await placemarkFromCoordinates(latitude, longitude);
Placemark place = placemarks[0];
if (place.thoroughfare != '' || place.subThoroughfare != '') {
address =
"${place.thoroughfare}, ${place.subThoroughfare} ${place.subLocality}, ${place.locality}, ${place.administrativeArea}";
} else {
address = '';
}
return address;
}
@override
Widget build(BuildContext context) {
List<String> opc = ["Servicio", "Opción 1", "Opción 2", "Opción 3"];
@@ -74,201 +139,300 @@ class _ServiceScreenState extends State<ServiceScreen> {
drawer: DrawerMenu(),
body: SingleChildScrollView(
reverse: true,
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: Builder(
builder: (BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
shape: const CircleBorder(),
elevation: 3,
minimumSize: const Size(50, 50),
),
child: const Icon(
Icons.menu,
color: Colors.black,
size: 30,
),
onPressed: () {
Scaffold.of(context).openDrawer();
},
);
},
),
),
Padding(
padding: const EdgeInsets.only(top: 23, left: 100, right: 25),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.4),
spreadRadius: 1,
blurRadius: 2,
offset:
const Offset(1, 2), // changes position of shadow
),
],
),
child: DropdownButtonFormField(
value: defaultValue,
elevation: 0,
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: BorderSide.none,
),
),
items: opc.map((e) {
return DropdownMenuItem(
value: e,
child: Text(
e,
style: const TextStyle(fontWeight: FontWeight.bold),
),
);
}).toList(),
onChanged: (value) {
print(value);
},
),
),
),
],
),
),
bottomNavigationBar: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(50), topLeft: Radius.circular(50))),
height: MediaQuery.of(context).size.height / 2.3,
child: Column(
children: [
const SizedBox(height: 15),
SizedBox(
width: 300,
child: Form(
child: Column(
children: [
TextFormField(
// controller: _cedulaController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.near_me),
hintText: 'Dirección'),
),
const SizedBox(height: 15),
TextFormField(
// controller: _cedulaController,
readOnly: true,
onTap: () async {
final String? profesional = await Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return const ProfessionalScreen();
},
),
) as String?;
if (profesional != null) {
Stack(
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: initialCameraPosition,
markers: markers,
zoomControlsEnabled: false,
onMapCreated: (GoogleMapController controller) {
googleMapController = controller;
},
onCameraIdle: () {
if (coordinates != null) {
getLocationName(
coordinates.latitude, coordinates.longitude)
.then((locationName) {
setState(() {
// _profession = profesional;
_locationController.text = locationName;
});
}
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.assignment_ind_rounded),
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Seleccionar profesional'),
),
const SizedBox(height: 15),
Row(
children: [
SizedBox(
width: 150,
child: TextFormField(
onTap: () {
_selectDate(context);
},
readOnly: true,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.calendar_month),
suffixIcon: _selectedDate == null
? const Icon(Icons.arrow_drop_down)
: null,
hintText: 'Fecha',
),
controller: TextEditingController(
text: _selectedDate == null
? ''
: formatter.format(_selectedDate!)),
});
}
},
// onCameraIdle: () {
// setState(() {
// if (coordinates != null) {
// placemarkFromCoordinates(coordinates.target.latitude, coordinates.target.longitude);
// _locationController.text = coordinates.toString();
// }
// });
// },
onCameraMove: (position) {
setState(() {
coordinates = position.target;
});
},
gestureRecognizers: <
Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
},
),
),
const Positioned(
bottom: 0,
right: 0,
left: 0,
top: 0,
child: Icon(
Icons.location_on,
size: 40,
color: Colors.red,
),
),
Positioned(
bottom: 10,
right: 20,
child: FloatingActionButton(
onPressed: () async {
try {
Position position = await _determinePosition();
googleMapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
position.latitude,
position.longitude,
),
zoom: 17),
),
);
setState(() {});
} catch (e) {
Get.snackbar(
'ubicación desactivada',
'Por favor activa la ubicacion de tu telefono.',
snackPosition: SnackPosition.TOP,
);
}
// markers.clear();
// markers.add(Marker(
// markerId: const MarkerId('currentLocation'),
// position:
// LatLng(position.latitude, position.longitude)));
},
elevation: 0,
child: const Icon(Icons.location_on),
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Builder(
builder: (BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
shape: const CircleBorder(),
elevation: 3,
minimumSize: const Size(50, 50),
),
SizedBox(
width: 150,
child: TextFormField(
onTap: () {
_selectTime(context);
},
readOnly: true,
decoration: const InputDecoration(
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Hora',
),
controller: TextEditingController(
text: _selectedTime == null
? ''
: ' ${_selectedTime!.format(context)}'),
),
child: const Icon(
Icons.menu,
color: Colors.black,
size: 30,
),
onPressed: () {
Scaffold.of(context).openDrawer();
},
);
},
),
),
Padding(
padding:
const EdgeInsets.only(top: 23, left: 100, right: 25),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.4),
spreadRadius: 1,
blurRadius: 2,
offset: const Offset(
1, 2), // changes position of shadow
),
],
),
const SizedBox(height: 15),
TextFormField(
// controller: _cedulaController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.message_outlined),
hintText: 'Observaciones'),
),
const SizedBox(height: 30),
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF2BA4EC),
shape: RoundedRectangleBorder(
child: DropdownButtonFormField(
value: defaultValue,
elevation: 0,
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: BorderSide.none,
),
elevation: 0,
minimumSize: const Size(230, 50),
),
child: const Text(
'Solicitar servicio',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
items: opc.map((e) {
return DropdownMenuItem(
value: e,
child: Text(
e,
style:
const TextStyle(fontWeight: FontWeight.bold),
),
);
}).toList(),
onChanged: (value) {
print(value);
},
),
),
),
],
),
Container(
width: double.infinity,
decoration: const BoxDecoration(color: Colors.white),
child: Column(
children: [
const SizedBox(height: 5),
SizedBox(
width: 320,
child: Form(
child: Column(
children: [
TextFormField(
controller: _locationController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.near_me),
hintText: 'Dirección'),
),
const SizedBox(height: 15),
TextFormField(
// controller: _cedulaController,
readOnly: true,
onTap: () async {
final String? profesional =
await Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return const ProfessionalScreen();
},
),
) as String?;
if (profesional != null) {
setState(() {
// _profession = profesional;
});
}
},
decoration: const InputDecoration(
prefixIcon:
Icon(Icons.assignment_ind_rounded),
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Seleccionar profesional'),
),
const SizedBox(height: 15),
Row(
children: [
SizedBox(
width: 180,
child: TextFormField(
onTap: () {
_selectDate(context);
},
readOnly: true,
decoration: InputDecoration(
prefixIcon:
const Icon(Icons.calendar_month),
suffixIcon: _selectedDate == null
? const Icon(Icons.arrow_drop_down)
: null,
hintText: 'Fecha',
),
controller: TextEditingController(
text: _selectedDate == null
? ''
: formatter.format(_selectedDate!)),
),
),
SizedBox(
width: 140,
child: TextFormField(
onTap: () {
_selectTime(context);
},
readOnly: true,
decoration: const InputDecoration(
suffixIcon: Icon(Icons.arrow_drop_down),
hintText: 'Hora',
),
controller: TextEditingController(
text: _selectedTime == null
? ''
: ' ${_selectedTime!.format(context)}'),
),
),
],
),
const SizedBox(height: 15),
TextFormField(
// controller: _cedulaController,
decoration: const InputDecoration(
prefixIcon: Icon(Icons.message_outlined),
hintText: 'Observaciones'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF2BA4EC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
elevation: 0,
minimumSize: const Size(230, 50),
),
child: const Text(
'Solicitar servicio',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
],
),
),
],
),
),
],
),
),
],