chat primera face

This commit is contained in:
Juan Felipe Duarte
2023-05-03 17:07:26 -05:00
parent f1571e6374
commit 1a0e33328e
16 changed files with 785 additions and 95 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

+4 -1
View File
@@ -8,10 +8,11 @@ import 'package:prosappco/src/screens/city.dart';
import 'package:prosappco/src/screens/login.dart'; import 'package:prosappco/src/screens/login.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:prosappco/src/screens/login_email.dart'; import 'package:prosappco/src/screens/login_email.dart';
import 'package:prosappco/src/screens/my_services.dart';
import 'package:prosappco/src/screens/my_services_pro.dart';
import 'package:prosappco/src/screens/new_number.dart'; import 'package:prosappco/src/screens/new_number.dart';
import 'package:prosappco/src/screens/new_password.dart'; import 'package:prosappco/src/screens/new_password.dart';
import 'package:prosappco/src/screens/profession.dart'; import 'package:prosappco/src/screens/profession.dart';
import 'package:prosappco/src/screens/professional.dart';
import 'package:prosappco/src/screens/professional_profile.dart'; import 'package:prosappco/src/screens/professional_profile.dart';
import 'package:prosappco/src/screens/professional_revision.dart'; import 'package:prosappco/src/screens/professional_revision.dart';
import 'package:prosappco/src/screens/profile.dart'; import 'package:prosappco/src/screens/profile.dart';
@@ -63,6 +64,8 @@ class MyApp extends StatelessWidget {
'/profilePro': (context) => const ProfilePro(), '/profilePro': (context) => const ProfilePro(),
'/calendar': (context) => const CalendarScreen(), '/calendar': (context) => const CalendarScreen(),
'/solicitud': (context) => SolicitudScreen(), '/solicitud': (context) => SolicitudScreen(),
'/misserviciospro': (context) => MyServicesProScreen(),
'/misservicios': (context) => MyServicesScreen(),
}, },
onGenerateRoute: (settings) { onGenerateRoute: (settings) {
throw Exception('Ruta desconocida: ${settings.name}'); throw Exception('Ruta desconocida: ${settings.name}');
+8 -2
View File
@@ -7,7 +7,6 @@ import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/models/scores_model.dart'; import 'package:prosappco/src/models/scores_model.dart';
import 'package:prosappco/src/models/user_model.dart'; import 'package:prosappco/src/models/user_model.dart';
import 'package:prosappco/src/screens/profile.dart'; import 'package:prosappco/src/screens/profile.dart';
import 'package:prosappco/src/screens/solicitudes.dart';
class DrawerMenu extends StatefulWidget { class DrawerMenu extends StatefulWidget {
@override @override
@@ -106,7 +105,14 @@ class _DrawerMenuState extends State<DrawerMenu> {
child: Column( child: Column(
children: [ children: [
ListTile( ListTile(
onTap: () {}, onTap: () {
if (ModalRoute.of(context)?.settings.name !=
'/misservicios') {
Navigator.pushNamed(context, '/misservicios');
} else {
Scaffold.of(context).openEndDrawer();
}
},
leading: const Icon( leading: const Icon(
Icons.history, Icons.history,
color: Colors.black, color: Colors.black,
+8 -1
View File
@@ -112,7 +112,14 @@ class _DrawerProfessionalState extends State<DrawerProfessional> {
child: Column( child: Column(
children: [ children: [
ListTile( ListTile(
onTap: () {}, onTap: () {
if (ModalRoute.of(context)?.settings.name !=
'/misserviciospro') {
Navigator.pushNamed(context, '/misserviciospro');
} else {
Scaffold.of(context).openEndDrawer();
}
},
leading: const Icon( leading: const Icon(
Icons.history, Icons.history,
color: Colors.black, color: Colors.black,
+37
View File
@@ -0,0 +1,37 @@
import 'package:cloud_firestore/cloud_firestore.dart';
class ChatModel {
List<MessageModel> messages;
ChatModel({required this.messages});
static ChatModel fromDocumentSnapshot(
DocumentSnapshot<Map<String, dynamic>> snapshot) {
try {
List<MessageModel> messages = [];
List<dynamic> messagesData = snapshot.get('message') ?? [];
for (var data in messagesData) {
messages.add(MessageModel(
user: data['user'] ?? '',
content: data['content'] ?? '',
timestamp: (data['timestamp'] as Timestamp).toDate(),
));
}
return ChatModel(messages: messages);
} catch (e) {
print('error $e');
return ChatModel(messages: []);
}
}
}
class MessageModel {
String user;
String content;
DateTime timestamp;
MessageModel(
{required this.user, required this.content, required this.timestamp});
}
+32 -2
View File
@@ -16,6 +16,7 @@ class EventoService {
String address, String address,
double latitude, double latitude,
double longitude, double longitude,
String status,
) async { ) async {
try { try {
DateTime ahora = DateTime.now(); DateTime ahora = DateTime.now();
@@ -33,6 +34,7 @@ class EventoService {
'address': address, 'address': address,
'latitude': latitude, 'latitude': latitude,
'longitude': longitude, 'longitude': longitude,
'status': status,
'Timestamp': ahora 'Timestamp': ahora
}).then((value) { }).then((value) {
FirebaseFirestore.instance.collection('users').doc(uid).update({ FirebaseFirestore.instance.collection('users').doc(uid).update({
@@ -72,17 +74,18 @@ Future<List<Event>> getByProId(String day) async {
} }
} }
Future<List<Event>> getByProIdAll() async { Future<List<Event>> getByProIdAll(String state1, String state2) async {
try { try {
var snapshot = await FirebaseFirestore.instance var snapshot = await FirebaseFirestore.instance
.collection('services') .collection('services')
.where('professional_id', isEqualTo: uid) .where('professional_id', isEqualTo: uid)
.get(); .where('status', whereIn: [state1, state2]).get();
List<Event> eventos = []; List<Event> eventos = [];
for (var element in snapshot.docs) { for (var element in snapshot.docs) {
final event = Event.fromJson(element.data()); final event = Event.fromJson(element.data());
event.scoresModel = await ScoresModel.scoreTo(event.userId, false, false); event.scoresModel = await ScoresModel.scoreTo(event.userId, false, false);
event.id = element.id;
eventos.add(event); eventos.add(event);
} }
print('eventos $eventos'); print('eventos $eventos');
@@ -94,6 +97,7 @@ Future<List<Event>> getByProIdAll() async {
} }
class Event { class Event {
String? id;
String title; String title;
String? description; String? description;
String day; String day;
@@ -105,9 +109,11 @@ class Event {
String? address; String? address;
double? longitud; double? longitud;
double? latitud; double? latitud;
String status;
ScoresModel? scoresModel; ScoresModel? scoresModel;
Event({ Event({
this.id,
required this.title, required this.title,
this.description, this.description,
required this.day, required this.day,
@@ -119,10 +125,12 @@ class Event {
this.address, this.address,
this.longitud, this.longitud,
this.latitud, this.latitud,
this.status = 'pendiente',
}); });
factory Event.fromJson(Map<String, dynamic> json) { factory Event.fromJson(Map<String, dynamic> json) {
return Event( return Event(
id: json['id'] ?? '',
title: json['title'], title: json['title'],
description: json['description'], description: json['description'],
day: json['day'], day: json['day'],
@@ -134,6 +142,7 @@ class Event {
address: json['address'] ?? '', address: json['address'] ?? '',
longitud: json['longitude'] ?? 0, longitud: json['longitude'] ?? 0,
latitud: json['latitude'] ?? 0, latitud: json['latitude'] ?? 0,
status: json['status'],
); );
} }
@@ -170,4 +179,25 @@ class Event {
return []; return [];
} }
} }
static Future<List<Event>> getEventsAllByIdStatus(
String uid, String state) async {
try {
var snapshot = await FirebaseFirestore.instance
.collection('services')
.where('professional_id', isEqualTo: uid)
.where('status', isEqualTo: state)
.get();
List<Event> eventos = [];
for (var element in snapshot.docs) {
eventos.add(Event.fromJson(element.data()));
}
print('eventos $eventos');
return eventos;
} catch (e) {
print('Error getByProId $e');
return [];
}
}
} }
+33
View File
@@ -0,0 +1,33 @@
import 'package:cloud_firestore/cloud_firestore.dart';
class SettingModel {
final bool domicilios;
SettingModel(this.domicilios);
static Future<SettingModel> fromJson(Map<String, dynamic> json) async {
try {
if (json == null) return SettingModel(false);
return SettingModel(json['habilitado']);
} catch (e) {
print('Error settings: $e');
return SettingModel(false);
}
}
static Future<SettingModel> getDomiciliosSettings() async {
try {
final DocumentSnapshot<Map<String, dynamic>> snapshot =
await FirebaseFirestore.instance
.collection('settings')
.doc('domicilios')
.get();
final Map<String, dynamic>? data = snapshot.data();
return fromJson(data!);
} catch (e) {
print('Error getting settings: $e');
return SettingModel(false);
}
}
}
+8 -5
View File
@@ -61,9 +61,10 @@ class _CalendarScreenState extends State<CalendarScreen> {
super.initState(); super.initState();
if (_events == null) { if (_events == null) {
Event.getEventsAllById(uid ?? "").then((value) => setState(() { Event.getEventsAllByIdStatus(uid ?? "", 'aprobado')
_events = value; .then((value) => setState(() {
})); _events = value;
}));
} }
} }
@@ -293,14 +294,16 @@ class _CalendarScreenState extends State<CalendarScreen> {
'', '',
'', '',
0, 0,
0) 0,
'aprobado')
.then((value) { .then((value) {
Navigator.pop(context); Navigator.pop(context);
_titleController.text = ''; _titleController.text = '';
_descriptionController.text = ''; _descriptionController.text = '';
}); });
Event.getEventsAllById(uid ?? "").then( Event.getEventsAllByIdStatus(uid ?? "", 'aprobado')
.then(
(value) => setState(() { (value) => setState(() {
_events = value; _events = value;
}), }),
+109
View File
@@ -0,0 +1,109 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/chat_model.dart';
class ChatScreen extends StatefulWidget {
final String eventoId;
const ChatScreen({super.key, required this.eventoId});
@override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _textController = TextEditingController();
final uid = AuthenticationRepository.instance.getCurrentUserUid();
@override
Widget build(BuildContext context) {
String textoIngresado = _textController.text;
return Scaffold(
appBar: PopAppbar(
onPressed: () {
Navigator.pop(context);
},
label: 'Mensajes'),
body: Column(
children: [
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('chats')
.doc(widget.eventoId)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
final data = snapshot.data!;
final chat = ChatModel.fromDocumentSnapshot(data);
print('messages ${chat.messages}');
return Column(children: [
...chat.messages.map(
(e) => ListTile(
title: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${e.content}, ',
style: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
// TextSpan(
// text: DateFormat('dd MMM', 'es')
// .format(DateTime.parse(e.day)),
// style: const TextStyle(
// color: Colors.grey,
// fontSize: 16,
// ),
// ),
],
),
),
),
)
]);
// ListTile(
// title: Text('${}'),
// );
},
),
TextFormField(
controller: _textController,
),
IconButton(
onPressed: () async {
final nuevoMensaje = MessageModel(
user: uid!,
content: _textController.text,
timestamp: DateTime.now());
final nuevoMensajeMap = {
'user': nuevoMensaje.user,
'content': nuevoMensaje.content,
'timestamp': nuevoMensaje.timestamp,
};
FirebaseFirestore.instance
.collection('chats')
.doc(widget.eventoId)
.update({
'message': FieldValue.arrayUnion([nuevoMensajeMap])
});
_textController.clear();
},
icon: const Icon(Icons.send))
],
),
);
}
}
+108 -23
View File
@@ -1,5 +1,7 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@@ -8,6 +10,7 @@ import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/event_model.dart'; import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/models/scores_model.dart'; import 'package:prosappco/src/models/scores_model.dart';
import 'package:prosappco/src/models/user_model.dart'; import 'package:prosappco/src/models/user_model.dart';
import 'package:prosappco/src/screens/chat.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:community_material_icon/community_material_icon.dart'; import 'package:community_material_icon/community_material_icon.dart';
@@ -213,6 +216,44 @@ class _CitaScreenState extends State<CitaScreen> {
), ),
), ),
const SizedBox(width: 20), const SizedBox(width: 20),
ElevatedButton(
onPressed: () async {
await FirebaseFirestore.instance
.collection('chats')
.doc(widget.evento.id)
.set({});
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return ChatScreen(eventoId: widget.evento.id!);
},
),
);
},
style: ElevatedButton.styleFrom(
foregroundColor: const Color(0xFF2BA4EC),
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
side: const BorderSide(
color: Color(0xFF2BA4EC),
width: 2,
),
),
),
child: const Padding(
padding:
EdgeInsets.symmetric(vertical: 18, horizontal: 0),
child: Icon(
Icons.message,
size: 30,
color: Color(0xFF2BA4EC),
),
),
),
const SizedBox(width: 20),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
_sendWhatsapp(); _sendWhatsapp();
@@ -280,32 +321,76 @@ class _CitaScreenState extends State<CitaScreen> {
child: Text('${widget.evento.address}')) child: Text('${widget.evento.address}'))
], ],
), ),
) ),
], ],
), ),
), ),
Padding( widget.evento.status == 'pendiendo'
padding: const EdgeInsets.only(bottom: 30), ? Padding(
child: ElevatedButton( padding: const EdgeInsets.only(bottom: 30),
onPressed: () {}, child: Column(
style: ElevatedButton.styleFrom( children: [
backgroundColor: const Color(0xFFEC2B2B), Padding(
shape: RoundedRectangleBorder( padding: const EdgeInsets.only(bottom: 20),
borderRadius: BorderRadius.circular(50), child: ElevatedButton(
), onPressed: () {
elevation: 0, FirebaseFirestore.instance
minimumSize: const Size(230, 60), .collection("services")
), .doc('${widget.evento.id}')
child: const Text( .update({"status": "aprobado"}).then((value) {
'Cancelar servicio', Navigator.pushReplacementNamed(
style: TextStyle( context, '/solicitud');
color: Colors.white, });
fontWeight: FontWeight.bold, },
fontSize: 18, style: ElevatedButton.styleFrom(
), backgroundColor: const Color(0xFF2BA4EC),
), shape: RoundedRectangleBorder(
), borderRadius: BorderRadius.circular(50),
), ),
elevation: 0,
minimumSize: const Size(230, 60),
),
child: const Text(
'Aceptar',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
),
ElevatedButton(
onPressed: () {
FirebaseFirestore.instance
.collection("services")
.doc('${widget.evento.id}')
.update({"status": "denegado"}).then((value) {
Navigator.pushReplacementNamed(
context, '/solicitud');
});
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFEC2B2B),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
elevation: 0,
minimumSize: const Size(230, 60),
),
child: const Text(
'Cancelar servicio',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
],
),
)
: const SizedBox(),
], ],
), ),
); );
+151
View File
@@ -0,0 +1,151 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:intl/intl.dart';
import 'package:prosappco/src/components/drawer_professional.dart';
import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/screens/cita.dart';
class MyServicesScreen extends StatefulWidget {
MyServicesScreen({super.key});
@override
State<MyServicesScreen> createState() => _MyServicesScreenState();
}
class _MyServicesScreenState extends State<MyServicesScreen> {
DateTime today = DateTime.now();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: PopAppbar(
onPressed: () {
Navigator.pop(context);
},
label: 'Mis servicios'),
drawer: DrawerProfessional(),
body: SingleChildScrollView(
child: Column(
children: [
_eventList(),
],
),
),
),
);
}
Widget _eventList() {
return FutureBuilder(
future: getByProIdAll('aprobado', 'denegado'),
builder: (BuildContext context, AsyncSnapshot<List<Event>> snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
List<Event> eventos = [];
try {
eventos.addAll(snapshot.data!);
} catch (e) {
print("Error" + e.toString());
}
if (eventos.isEmpty) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 50),
child: Center(child: Text('No tienes citas')),
);
}
return Column(
children: [
...eventos.map(
(event) => ListTile(
tileColor: event.status == 'aprobado'
? Colors.green[100]
: Colors.red[100],
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return CitaScreen(evento: event);
},
),
);
},
leading: Text(event.range1Hour1),
title: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${event.title}, ',
style: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
TextSpan(
text: DateFormat('dd MMM', 'es')
.format(DateTime.parse(event.day)),
style: const TextStyle(
color: Colors.grey,
fontSize: 16,
),
),
],
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
RatingBar.builder(
initialRating: event.scoresModel?.average ?? 0,
minRating: 1,
direction: Axis.horizontal,
allowHalfRating: true,
itemCount: 5,
itemSize: 25,
maxRating: 5,
itemPadding:
const EdgeInsets.symmetric(horizontal: 0),
itemBuilder: (context, _) => const Icon(
Icons.star,
color: Color(0xFF2BA4EC),
),
onRatingUpdate: (rating) {},
ignoreGestures: true,
),
const SizedBox(width: 5),
Text(
'(${event.scoresModel?.total.toString()}) ${event.scoresModel?.average.toString()}'),
],
),
Text(
'" ${event.description}"',
style: const TextStyle(fontStyle: FontStyle.italic),
),
],
),
trailing: const Icon(Icons.keyboard_arrow_right),
),
),
],
);
},
);
}
}
+161
View File
@@ -0,0 +1,161 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:intl/intl.dart';
import 'package:prosappco/src/components/drawer_professional.dart';
import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/screens/cita.dart';
class MyServicesProScreen extends StatefulWidget {
MyServicesProScreen({super.key});
@override
State<MyServicesProScreen> createState() => _MyServicesProScreenState();
}
class _MyServicesProScreenState extends State<MyServicesProScreen> {
DateTime today = DateTime.now();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: PopAppbar(
onPressed: () {
Navigator.pop(context);
},
label: 'Mis servicios'),
drawer: DrawerProfessional(),
body: SingleChildScrollView(
child: Column(
children: [
_eventList(),
],
),
),
),
);
}
Widget _eventList() {
return FutureBuilder(
future: getByProIdAll('aprobado', 'denegado'),
builder: (BuildContext context, AsyncSnapshot<List<Event>> snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
List<Event> eventos = [];
try {
eventos.addAll(snapshot.data!);
} catch (e) {
print("Error" + e.toString());
}
if (eventos.isEmpty) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 50),
child: Center(child: Text('No tienes citas')),
);
}
return Column(
children: [
...eventos.map(
(event) => ListTile(
tileColor: event.status == 'aprobado'
? Colors.blue[100]
: Colors.red[100],
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext context) {
return CitaScreen(evento: event);
},
),
);
},
leading: event.status == 'aprobado'
? const Icon(
Icons.check,
color: Colors.blue,
size: 40,
)
: const Icon(
Icons.close,
color: Colors.red,
size: 40,
),
title: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${event.title}, ',
style: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
TextSpan(
text:
'${DateFormat('dd MMM', 'es').format(DateTime.parse(event.day))} - ${event.range1Hour1}',
style: const TextStyle(
color: Colors.grey,
fontSize: 16,
),
),
],
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
RatingBar.builder(
initialRating: event.scoresModel?.average ?? 0,
minRating: 1,
direction: Axis.horizontal,
allowHalfRating: true,
itemCount: 5,
itemSize: 25,
maxRating: 5,
itemPadding:
const EdgeInsets.symmetric(horizontal: 0),
itemBuilder: (context, _) => const Icon(
Icons.star,
color: Color(0xFF2BA4EC),
),
onRatingUpdate: (rating) {},
ignoreGestures: true,
),
const SizedBox(width: 5),
Text(
'(${event.scoresModel?.total.toString()}) ${event.scoresModel?.average.toString()}'),
],
),
Text(
'" ${event.description}"',
style: const TextStyle(fontStyle: FontStyle.italic),
),
],
),
trailing: const Icon(Icons.keyboard_arrow_right),
),
),
],
);
},
);
}
}
+30 -26
View File
@@ -3,7 +3,6 @@ import 'package:diacritic/diacritic.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/photo_view.dart'; import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
@@ -171,28 +170,30 @@ class _ProfessionalScreenState extends State<ProfessionalScreen> {
_photo = await AuthenticationRepository.instance.getPhoto(user.id); _photo = await AuthenticationRepository.instance.getPhoto(user.id);
if (data['estado'] == 'activo') { if (data['estado'] == 'activo') {
List<String> especializaciones; if (user.id != uid) {
List<String> especializaciones;
especializaciones = (data['especializaciones'] as List<dynamic>) especializaciones = (data['especializaciones'] as List<dynamic>)
.map((e) => e.toString()) .map((e) => e.toString())
.toList(); .toList();
if (widget.profession == data['profesion'] || if (widget.profession == data['profesion'] ||
widget.profession == '') { widget.profession == '') {
Professional professional = Professional( Professional professional = Professional(
id: user.id, id: user.id,
name: data['name'], name: data['name'],
professionName: data['profesion'], professionName: data['profesion'],
cityName: data['city'], cityName: data['city'],
professionalRef: storage.ref().child(_photo), professionalRef: storage.ref().child(_photo),
professionalEspecializado: especializaciones, professionalEspecializado: especializaciones,
ubicacion: data['ubicacion'] ?? '', ubicacion: data['ubicacion'] ?? '',
realAddress: data['address'] ?? '', realAddress: data['address'] ?? '',
latitude: data['latitude'] ?? 0, latitude: data['latitude'] ?? 0,
longitude: data['longitude'] ?? 0, longitude: data['longitude'] ?? 0,
scores: await ScoresModel.scoreTo(user.id, true, true), scores: await ScoresModel.scoreTo(user.id, true, true),
); );
professionals.add(professional); professionals.add(professional);
}
} }
} }
} }
@@ -211,13 +212,16 @@ class _ProfessionalScreenState extends State<ProfessionalScreen> {
setState(() { setState(() {
if (_professionals != null) { if (_professionals != null) {
if (searchController.text.isEmpty) { if (searchController.text.isEmpty) {
filteredProfessionals = _professionals!; filteredProfessionals = _professionals!
.where((professional) => professional.id != uid)
.toList();
} else { } else {
filteredProfessionals = _professionals! filteredProfessionals = _professionals!
.where((professional) => removeDiacritics(professional.name) .where((professional) =>
.toLowerCase() removeDiacritics(professional.name).toLowerCase().contains(
.contains( removeDiacritics(
removeDiacritics(searchController.text.toLowerCase()))) searchController.text.toLowerCase())) &&
professional.id != uid)
.toList(); .toList();
} }
} }
+20 -13
View File
@@ -1,7 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -9,10 +8,10 @@ import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/banner_photo.dart'; import 'package:prosappco/src/components/banner_photo.dart';
import 'package:prosappco/src/components/drawer_professional.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/components/primary_btn.dart'; import 'package:prosappco/src/components/primary_btn.dart';
import 'package:prosappco/src/components/schedule_picker.dart'; import 'package:prosappco/src/components/schedule_picker.dart';
import 'package:prosappco/src/models/setting_model.dart';
import 'package:prosappco/src/screens/horario.dart'; import 'package:prosappco/src/screens/horario.dart';
import 'package:prosappco/src/screens/professional.dart'; import 'package:prosappco/src/screens/professional.dart';
import 'package:prosappco/src/screens/professional_direccion.dart'; import 'package:prosappco/src/screens/professional_direccion.dart';
@@ -41,12 +40,18 @@ class _ProfileProState extends State<ProfilePro> {
var _direccion = '...'; var _direccion = '...';
var _ubicacion = '...'; var _ubicacion = '...';
var _opcionalAddress = '...'; var _opcionalAddress = '...';
SettingModel? setting_domicilio;
Map<String, Schedule>? _horarios; Map<String, Schedule>? _horarios;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (setting_domicilio == null) {
SettingModel.getDomiciliosSettings().then(
(SettingModel value) => setState(() => setting_domicilio = value),
);
}
final uid = AuthenticationRepository.instance.getCurrentUserUid(); final uid = AuthenticationRepository.instance.getCurrentUserUid();
@@ -283,17 +288,19 @@ class _ProfileProState extends State<ProfilePro> {
), ),
), ),
), ),
const Divider( if (setting_domicilio?.domicilios == true)
color: Colors.white, const Divider(
height: 12, color: Colors.white,
), height: 12,
customSwitch( ),
'Servicio a domicilio', if (setting_domicilio?.domicilios == true)
domicilioValue, customSwitch(
(value) { 'Servicio a domicilio',
domicilioValue = value; domicilioValue,
}, (value) {
), domicilioValue = value;
},
),
const Divider(), const Divider(),
customSwitch( customSwitch(
'Servicio en sitio', 'Servicio en sitio',
+73 -18
View File
@@ -1,4 +1,5 @@
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:community_material_icon/community_material_icon.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@@ -88,7 +89,7 @@ class _ServiceScreenState extends State<ServiceScreen> {
final DateTime? picked = await showDatePicker( final DateTime? picked = await showDatePicker(
context: context, context: context,
initialDate: now, initialDate: now,
firstDate: DateTime(now.year), firstDate: now,
lastDate: DateTime(now.year + 1), lastDate: DateTime(now.year + 1),
// builder: (context, child) { // builder: (context, child) {
// return Theme(data: ThemeData.dark(), child: child!); // return Theme(data: ThemeData.dark(), child: child!);
@@ -130,10 +131,19 @@ class _ServiceScreenState extends State<ServiceScreen> {
final FirebaseStorage storage = FirebaseStorage.instance; final FirebaseStorage storage = FirebaseStorage.instance;
final uid = AuthenticationRepository.instance.getCurrentUserUid(); final uid = AuthenticationRepository.instance.getCurrentUserUid();
BitmapDescriptor? _markerIcon;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
BitmapDescriptor.fromAssetImage(
ImageConfiguration(size: Size(48, 48)), 'images/pro_marke.png')
.then((icon) {
setState(() {
_markerIcon = icon;
});
});
try { try {
getUsersWithActiveStatus().then((value) { getUsersWithActiveStatus().then((value) {
for (var doc in value) { for (var doc in value) {
@@ -142,6 +152,7 @@ class _ServiceScreenState extends State<ServiceScreen> {
if (element['latitude'] != null && element['longitude'] != null) { if (element['latitude'] != null && element['longitude'] != null) {
markers.add( markers.add(
Marker( Marker(
icon: _markerIcon!,
markerId: MarkerId(doc.id), markerId: MarkerId(doc.id),
position: LatLng( position: LatLng(
element['latitude'], element['latitude'],
@@ -448,7 +459,29 @@ class _ServiceScreenState extends State<ServiceScreen> {
width: 180, width: 180,
child: TextFormField( child: TextFormField(
onTap: () { onTap: () {
_selectDate(context); if (_profesionalController
.text.isNotEmpty) {
_selectDate(context);
} else {
final snackBar = SnackBar(
backgroundColor: Colors.blue,
content: const Text(
'Selecciona un profesional',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10.0),
),
);
ScaffoldMessenger.of(context)
.showSnackBar(snackBar);
}
}, },
readOnly: true, readOnly: true,
decoration: InputDecoration( decoration: InputDecoration(
@@ -469,7 +502,29 @@ class _ServiceScreenState extends State<ServiceScreen> {
width: 140, width: 140,
child: TextFormField( child: TextFormField(
onTap: () { onTap: () {
_selectTime(context); if (_profesionalController
.text.isNotEmpty) {
_selectTime(context);
} else {
final snackBar = SnackBar(
backgroundColor: Colors.blue,
content: const Text(
'Selecciona un profesional',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10.0),
),
);
ScaffoldMessenger.of(context)
.showSnackBar(snackBar);
}
}, },
readOnly: true, readOnly: true,
decoration: const InputDecoration( decoration: const InputDecoration(
@@ -508,21 +563,21 @@ class _ServiceScreenState extends State<ServiceScreen> {
UserModel.getUser(uid.toString()).then((value) { UserModel.getUser(uid.toString()).then((value) {
eventoService eventoService
.createEvent( .createEvent(
value.name, value.name,
_observacionController.text, _observacionController.text,
'${_selectedDate}Z', '${_selectedDate}Z',
_selectedTime!.format(context), _selectedTime!.format(context),
time2.format(context), time2.format(context),
professionalId, professionalId,
ubicacion, ubicacion,
_locationController.text, _locationController.text,
ubicacion != 'sitio' ubicacion != 'sitio'
? coordinates.latitude ? coordinates.latitude
: professionalLatitude, : professionalLatitude,
ubicacion != 'sitio' ubicacion != 'sitio'
? coordinates.longitude ? coordinates.longitude
: professionalLongitude, : professionalLongitude,
) 'pendiente')
.then((value) { .then((value) {
Navigator.push( Navigator.push(
context, context,
+3 -4
View File
@@ -4,7 +4,6 @@ import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:prosappco/src/components/drawer_professional.dart'; import 'package:prosappco/src/components/drawer_professional.dart';
import 'package:prosappco/src/models/event_model.dart'; import 'package:prosappco/src/models/event_model.dart';
import 'package:prosappco/src/models/scores_model.dart';
import 'package:prosappco/src/screens/cita.dart'; import 'package:prosappco/src/screens/cita.dart';
class SolicitudScreen extends StatefulWidget { class SolicitudScreen extends StatefulWidget {
@@ -52,7 +51,7 @@ class _SolicitudScreenState extends State<SolicitudScreen> {
Widget _eventList() { Widget _eventList() {
return FutureBuilder( return FutureBuilder(
future: getByProIdAll(), future: getByProIdAll('pendiente', ''),
builder: (BuildContext context, AsyncSnapshot<List<Event>> snapshot) { builder: (BuildContext context, AsyncSnapshot<List<Event>> snapshot) {
if (!snapshot.hasData) { if (!snapshot.hasData) {
return const Center( return const Center(
@@ -135,11 +134,11 @@ class _SolicitudScreenState extends State<SolicitudScreen> {
), ),
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
'(${event.scoresModel?.total.toString()}) ${event.scoresModel?.average.toString()}'), '(${event.scoresModel?.total.toString()}) ${event.scoresModel?.average.toString()}'),
], ],
), ),
Text( Text(
'" ${event.description} "', '" ${event.description}"',
style: const TextStyle(fontStyle: FontStyle.italic), style: const TextStyle(fontStyle: FontStyle.italic),
), ),
], ],