chat
This commit is contained in:
@@ -6,6 +6,8 @@ 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/models/user_model.dart';
|
import 'package:prosappco/src/models/user_model.dart';
|
||||||
import 'package:prosappco/src/screens/calendar.dart';
|
import 'package:prosappco/src/screens/calendar.dart';
|
||||||
|
import 'package:prosappco/src/screens/messages.dart';
|
||||||
|
import 'package:prosappco/src/screens/my_services_pro.dart';
|
||||||
import 'package:prosappco/src/screens/professional.dart';
|
import 'package:prosappco/src/screens/professional.dart';
|
||||||
import 'package:prosappco/src/screens/profile.dart';
|
import 'package:prosappco/src/screens/profile.dart';
|
||||||
import 'package:prosappco/src/screens/profile_pro.dart';
|
import 'package:prosappco/src/screens/profile_pro.dart';
|
||||||
@@ -113,12 +115,13 @@ class _DrawerProfessionalState extends State<DrawerProfessional> {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (ModalRoute.of(context)?.settings.name !=
|
Navigator.of(context).push(
|
||||||
'/misserviciospro') {
|
CupertinoPageRoute(
|
||||||
Navigator.pushNamed(context, '/misserviciospro');
|
builder: (BuildContext context) {
|
||||||
} else {
|
return MyServicesProScreen();
|
||||||
Scaffold.of(context).openEndDrawer();
|
},
|
||||||
}
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
leading: const Icon(
|
leading: const Icon(
|
||||||
Icons.history,
|
Icons.history,
|
||||||
@@ -172,7 +175,15 @@ class _DrawerProfessionalState extends State<DrawerProfessional> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return MessagesScreen();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
leading: const Icon(
|
leading: const Icon(
|
||||||
Icons.messenger_outline,
|
Icons.messenger_outline,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
|
|||||||
@@ -1,12 +1,24 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:prosappco/src/models/user_model.dart';
|
||||||
|
|
||||||
class ChatModel {
|
class ChatModel {
|
||||||
List<MessageModel> messages;
|
List<MessageModel> messages;
|
||||||
|
String professional_id;
|
||||||
|
String user_id;
|
||||||
|
UserModel? user;
|
||||||
|
UserModel? professional;
|
||||||
|
|
||||||
ChatModel({required this.messages});
|
ChatModel({
|
||||||
|
required this.messages,
|
||||||
|
required this.professional_id,
|
||||||
|
required this.user_id,
|
||||||
|
this.user,
|
||||||
|
this.professional,
|
||||||
|
});
|
||||||
|
|
||||||
static ChatModel fromDocumentSnapshot(
|
static Future<ChatModel> fromDocumentSnapshot2(
|
||||||
DocumentSnapshot<Map<String, dynamic>> snapshot) {
|
DocumentSnapshot<Map<String, dynamic>> snapshot,
|
||||||
|
bool fillUserModel) async {
|
||||||
try {
|
try {
|
||||||
List<MessageModel> messages = [];
|
List<MessageModel> messages = [];
|
||||||
List<dynamic> messagesData = snapshot.get('message') ?? [];
|
List<dynamic> messagesData = snapshot.get('message') ?? [];
|
||||||
@@ -19,12 +31,73 @@ class ChatModel {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ChatModel(messages: messages);
|
return ChatModel(
|
||||||
|
messages: messages,
|
||||||
|
professional_id: snapshot.get('professional_id'),
|
||||||
|
user_id: snapshot.get('user_id'),
|
||||||
|
user: fillUserModel
|
||||||
|
? await UserModel.getUser(snapshot.get('user_id'))
|
||||||
|
: null,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('error $e');
|
print('error $e');
|
||||||
return ChatModel(messages: []);
|
return ChatModel(messages: [], professional_id: '', user_id: '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
professional_id: snapshot.get('professional_id'),
|
||||||
|
user_id: snapshot.get('user_id'),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
print('error $e');
|
||||||
|
return ChatModel(messages: [], professional_id: '', user_id: '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<ChatModel>> getChatsByProId(String userReceived) async {
|
||||||
|
final receivedScoresQuery = FirebaseFirestore.instance
|
||||||
|
.collection('chats')
|
||||||
|
.where('professional_id', isEqualTo: userReceived);
|
||||||
|
|
||||||
|
final receivedScoresSnapshot = await receivedScoresQuery.get();
|
||||||
|
|
||||||
|
final receivedScores = await Future.wait(receivedScoresSnapshot.docs
|
||||||
|
.map((doc) async => await fromDocumentSnapshot2(doc, true))
|
||||||
|
.toList());
|
||||||
|
|
||||||
|
return receivedScores;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<ChatModel>> getChatsByUserId(String userReceived) async {
|
||||||
|
final receivedScoresQuery = FirebaseFirestore.instance
|
||||||
|
.collection('chats')
|
||||||
|
.where('user_id', isEqualTo: userReceived);
|
||||||
|
|
||||||
|
final receivedScoresSnapshot = await receivedScoresQuery.get();
|
||||||
|
|
||||||
|
final receivedScores = await Future.wait(receivedScoresSnapshot.docs
|
||||||
|
.map((doc) async => await fromDocumentSnapshot2(doc, true))
|
||||||
|
.toList());
|
||||||
|
|
||||||
|
return receivedScores;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageModel {
|
class MessageModel {
|
||||||
|
|||||||
@@ -96,6 +96,28 @@ Future<List<Event>> getByProIdAll(String state1, String state2) async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<Event>> getByUserIdAll(String state1, String state2) async {
|
||||||
|
try {
|
||||||
|
var snapshot = await FirebaseFirestore.instance
|
||||||
|
.collection('services')
|
||||||
|
.where('user_id', isEqualTo: uid)
|
||||||
|
.where('status', whereIn: [state1, state2]).get();
|
||||||
|
|
||||||
|
List<Event> eventos = [];
|
||||||
|
for (var element in snapshot.docs) {
|
||||||
|
final event = Event.fromJson(element.data());
|
||||||
|
event.scoresModel = await ScoresModel.scoreTo(event.userId, false, false);
|
||||||
|
event.id = element.id;
|
||||||
|
eventos.add(event);
|
||||||
|
}
|
||||||
|
print('eventos $eventos');
|
||||||
|
return eventos;
|
||||||
|
} catch (e) {
|
||||||
|
print('Error getByUserId $e');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Event {
|
class Event {
|
||||||
String? id;
|
String? id;
|
||||||
String title;
|
String title;
|
||||||
@@ -151,9 +173,17 @@ class Event {
|
|||||||
final snapshot = await FirebaseFirestore.instance
|
final snapshot = await FirebaseFirestore.instance
|
||||||
.collection('services')
|
.collection('services')
|
||||||
.doc(uid)
|
.doc(uid)
|
||||||
.get();
|
.get()
|
||||||
final Map<String, dynamic>? data = snapshot.data();
|
.then((docSnapshot) {
|
||||||
return Event.fromJson(data!);
|
if (docSnapshot.exists) {
|
||||||
|
print('info ${docSnapshot.data()}');
|
||||||
|
} else {
|
||||||
|
print('No se encontró ningún documento con la ruta especificada');
|
||||||
|
}
|
||||||
|
;
|
||||||
|
});
|
||||||
|
final Map<String, dynamic> data = snapshot.data();
|
||||||
|
return Event.fromJson(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error getting user: $e');
|
print('Error getting user: $e');
|
||||||
return Event(
|
return Event(
|
||||||
|
|||||||
@@ -5,26 +5,28 @@ import 'package:prosappco/src/screens/professional.dart';
|
|||||||
class UserModel {
|
class UserModel {
|
||||||
final String name;
|
final String name;
|
||||||
final String city;
|
final String city;
|
||||||
|
final String? profession;
|
||||||
final String? state;
|
final String? state;
|
||||||
final Reference? photo;
|
final Reference? photo;
|
||||||
|
|
||||||
UserModel(this.name, this.city, this.state, this.photo);
|
UserModel(this.name, this.city, this.profession, this.state, this.photo);
|
||||||
|
|
||||||
static Future<UserModel> fromJson(
|
static Future<UserModel> fromJson(
|
||||||
Map<String, dynamic>? json, String uid) async {
|
Map<String, dynamic>? json, String uid) async {
|
||||||
try {
|
try {
|
||||||
if (json == null) return UserModel('', '', null, null);
|
if (json == null) return UserModel('', '', '', null, null);
|
||||||
|
|
||||||
String? avatar = json['photo'];
|
String? avatar = json['photo'];
|
||||||
return UserModel(
|
return UserModel(
|
||||||
json['name'],
|
json['name'],
|
||||||
json['city'],
|
json['city'],
|
||||||
|
json['profesion'],
|
||||||
json['estado'],
|
json['estado'],
|
||||||
avatar != null ? storage.ref().child(avatar) : null,
|
avatar != null ? storage.ref().child(avatar) : null,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('XD user $e');
|
print('XD user $e');
|
||||||
return UserModel('', '', null, null);
|
return UserModel('', '', '', null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +38,7 @@ class UserModel {
|
|||||||
return fromJson(data, uid);
|
return fromJson(data, uid);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error getting user: $e');
|
print('Error getting user: $e');
|
||||||
return UserModel('', '', null, null);
|
return UserModel('', '', '', null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+236
-73
@@ -1,12 +1,16 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.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/pop_appbar.dart';
|
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||||
import 'package:prosappco/src/models/chat_model.dart';
|
import 'package:prosappco/src/models/chat_model.dart';
|
||||||
|
import 'package:prosappco/src/models/event_model.dart';
|
||||||
|
import 'package:prosappco/src/models/user_model.dart';
|
||||||
|
|
||||||
class ChatScreen extends StatefulWidget {
|
class ChatScreen extends StatefulWidget {
|
||||||
final String eventoId;
|
final Event evento;
|
||||||
const ChatScreen({super.key, required this.eventoId});
|
const ChatScreen({super.key, required this.evento});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ChatScreen> createState() => _ChatScreenState();
|
State<ChatScreen> createState() => _ChatScreenState();
|
||||||
@@ -15,6 +19,31 @@ class ChatScreen extends StatefulWidget {
|
|||||||
class _ChatScreenState extends State<ChatScreen> {
|
class _ChatScreenState extends State<ChatScreen> {
|
||||||
final _textController = TextEditingController();
|
final _textController = TextEditingController();
|
||||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||||
|
UserModel? user;
|
||||||
|
// ScoresModel? scoresModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
if (uid != widget.evento.userId) {
|
||||||
|
UserModel.getUser(widget.evento.userId).then(
|
||||||
|
(UserModel s) => setState(() => user = s),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
UserModel.getUser(widget.evento.professionalId).then(
|
||||||
|
(UserModel s) => setState(() => user = s),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (scoresModel == null) {
|
||||||
|
// ScoresModel.scoreTo(uid.toString(), false, false).then(
|
||||||
|
// (ScoresModel s) => setState(() => scoresModel = s),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -24,86 +53,220 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
label: 'Mensajes'),
|
label: 'Chat'),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
StreamBuilder(
|
Container(
|
||||||
stream: FirebaseFirestore.instance
|
decoration: BoxDecoration(
|
||||||
.collection('chats')
|
boxShadow: [
|
||||||
.doc(widget.eventoId)
|
BoxShadow(
|
||||||
.snapshots(),
|
color: Colors.grey.withOpacity(0.3),
|
||||||
builder: (context, snapshot) {
|
spreadRadius: 2,
|
||||||
if (!snapshot.hasData) {
|
blurRadius: 3,
|
||||||
return const Center(child: CircularProgressIndicator());
|
offset: const Offset(0, 2), // changes position of shadow
|
||||||
}
|
),
|
||||||
|
],
|
||||||
final data = snapshot.data!;
|
),
|
||||||
final chat = ChatModel.fromDocumentSnapshot(data);
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
print('messages ${chat.messages}');
|
color: const Color(0xFFD6F4FF),
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
return Column(children: [
|
child: ListTile(
|
||||||
...chat.messages.map(
|
leading: Padding(
|
||||||
(e) => ListTile(
|
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||||
title: RichText(
|
child: ReferencePhoto(
|
||||||
text: TextSpan(
|
ref: user?.photo,
|
||||||
children: [
|
size: 55,
|
||||||
TextSpan(
|
sizeCircle: 60,
|
||||||
text: '${e.content}, ',
|
),
|
||||||
style: const TextStyle(
|
),
|
||||||
color: Colors.black,
|
title: Text(
|
||||||
fontWeight: FontWeight.bold,
|
'${user?.name}',
|
||||||
fontSize: 16,
|
style: const TextStyle(
|
||||||
),
|
color: Colors.black, fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
// TextSpan(
|
subtitle: Text('${user?.profession}'),
|
||||||
// text: DateFormat('dd MMM', 'es')
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||||
// .format(DateTime.parse(e.day)),
|
),
|
||||||
// style: const TextStyle(
|
),
|
||||||
// color: Colors.grey,
|
),
|
||||||
// fontSize: 16,
|
Expanded(
|
||||||
// ),
|
child: SingleChildScrollView(
|
||||||
// ),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
],
|
reverse: true,
|
||||||
|
child: streamB(uid!),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 18),
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
controller: _textController,
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Mensaje',
|
||||||
|
hintStyle:
|
||||||
|
TextStyle(color: Colors.grey[600], fontSize: 16),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Colors.grey, width: 1.0),
|
||||||
|
borderRadius: BorderRadius.circular(50)),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Colors.grey, width: 1.0),
|
||||||
|
borderRadius: BorderRadius.circular(50)),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20, vertical: 15),
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.grey[200],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
const SizedBox(width: 12),
|
||||||
]);
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
final nuevoMensaje = MessageModel(
|
||||||
|
user: uid!,
|
||||||
|
content: _textController.text,
|
||||||
|
timestamp: DateTime.now());
|
||||||
|
|
||||||
// ListTile(
|
final nuevoMensajeMap = {
|
||||||
// title: Text('${}'),
|
'user': nuevoMensaje.user,
|
||||||
// );
|
'content': nuevoMensaje.content,
|
||||||
},
|
'timestamp': nuevoMensaje.timestamp,
|
||||||
|
};
|
||||||
|
|
||||||
|
FirebaseFirestore.instance
|
||||||
|
.collection('chats')
|
||||||
|
.doc(widget.evento.id)
|
||||||
|
.update({
|
||||||
|
'message': FieldValue.arrayUnion([nuevoMensajeMap])
|
||||||
|
});
|
||||||
|
|
||||||
|
_textController.clear();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 50,
|
||||||
|
width: 50,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
),
|
||||||
|
child: const Center(
|
||||||
|
child: Icon(
|
||||||
|
Icons.send,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
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))
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>> streamB(String uid) {
|
||||||
|
return StreamBuilder(
|
||||||
|
stream: FirebaseFirestore.instance
|
||||||
|
.collection('chats')
|
||||||
|
.doc(widget.evento.id)
|
||||||
|
.snapshots(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
|
||||||
|
final data = snapshot.data!;
|
||||||
|
final chat = ChatModel.fromDocumentSnapshot(data);
|
||||||
|
|
||||||
|
return Column(children: [
|
||||||
|
...chat.messages.map(
|
||||||
|
(e) => uid != e.user
|
||||||
|
? ListTile(
|
||||||
|
title: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(right: 60),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10, horizontal: 16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey.shade200,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topRight: Radius.circular(20),
|
||||||
|
bottomLeft: Radius.circular(20),
|
||||||
|
bottomRight: Radius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
e.content,
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 5),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Text(
|
||||||
|
DateFormat('h:mm a').format(e.timestamp),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.grey, fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ListTile(
|
||||||
|
title: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(left: 60),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10, horizontal: 16),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFD5EFFF),
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(20),
|
||||||
|
bottomLeft: Radius.circular(20),
|
||||||
|
bottomRight: Radius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
e.content,
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 5),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Text(
|
||||||
|
DateFormat('h:mm a').format(e.timestamp),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.grey, fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ListTile(
|
||||||
|
// title: Text('${}'),
|
||||||
|
// );
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-13
@@ -1,10 +1,10 @@
|
|||||||
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';
|
||||||
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';
|
||||||
|
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';
|
||||||
import 'package:prosappco/src/models/event_model.dart';
|
import 'package:prosappco/src/models/event_model.dart';
|
||||||
@@ -23,6 +23,7 @@ class CitaScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CitaScreenState extends State<CitaScreen> {
|
class _CitaScreenState extends State<CitaScreen> {
|
||||||
|
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||||
UserModel? user;
|
UserModel? user;
|
||||||
@override
|
@override
|
||||||
String nombre = '';
|
String nombre = '';
|
||||||
@@ -54,23 +55,40 @@ class _CitaScreenState extends State<CitaScreen> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
if (scoresModel == null) {
|
if (scoresModel == null) {
|
||||||
ScoresModel.scoreTo(widget.evento.userId.toString(), false, false).then(
|
if (uid != widget.evento.userId) {
|
||||||
(ScoresModel s) => setState(() {
|
ScoresModel.scoreTo(widget.evento.userId, false, false).then(
|
||||||
scoresModel = s;
|
(ScoresModel s) => setState(() {
|
||||||
}),
|
scoresModel = s;
|
||||||
);
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ScoresModel.scoreTo(widget.evento.professionalId, true, false).then(
|
||||||
|
(ScoresModel s) => setState(() {
|
||||||
|
scoresModel = s;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (nombre == '') {
|
if (nombre == '') {
|
||||||
UserModel.getUser(widget.evento.userId).then((value) {
|
if (uid != widget.evento.userId) {
|
||||||
setState(() {
|
UserModel.getUser(widget.evento.userId).then((value) {
|
||||||
nombre = value.name;
|
setState(() {
|
||||||
ref_photo = value.photo;
|
nombre = value.name;
|
||||||
|
ref_photo = value.photo;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
UserModel.getUser(widget.evento.professionalId).then((value) {
|
||||||
|
setState(() {
|
||||||
|
nombre = value.name;
|
||||||
|
ref_photo = value.photo;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -221,13 +239,17 @@ class _CitaScreenState extends State<CitaScreen> {
|
|||||||
await FirebaseFirestore.instance
|
await FirebaseFirestore.instance
|
||||||
.collection('chats')
|
.collection('chats')
|
||||||
.doc(widget.evento.id)
|
.doc(widget.evento.id)
|
||||||
.set({});
|
.set({
|
||||||
|
'professional_id': widget.evento.professionalId,
|
||||||
|
'user_id': widget.evento.userId
|
||||||
|
}, SetOptions(merge: true)).catchError((error) =>
|
||||||
|
print('Error al crear el documento: $error'));
|
||||||
|
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return ChatScreen(eventoId: widget.evento.id!);
|
return ChatScreen(evento: widget.evento);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import 'package:community_material_icon/community_material_icon.dart';
|
||||||
|
import 'package:flutter/cupertino.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';
|
||||||
|
import 'package:prosappco/src/models/event_model.dart';
|
||||||
|
import 'package:prosappco/src/models/user_model.dart';
|
||||||
|
import 'package:prosappco/src/screens/chat.dart';
|
||||||
|
|
||||||
|
class MessagesScreen extends StatefulWidget {
|
||||||
|
const MessagesScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MessagesScreen> createState() => _MessagesScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MessagesScreenState extends State<MessagesScreen> {
|
||||||
|
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||||
|
List<ChatModel> list = [];
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
ChatModel.getChatsByProId(uid!).then(
|
||||||
|
(List<ChatModel> s) => setState(() {
|
||||||
|
list = s;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: PopAppbar(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
label: 'Mensajes'),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: TextField(
|
||||||
|
// controller: searchController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Escriba un nombre',
|
||||||
|
prefixIcon: Icon(CommunityMaterialIcons.stethoscope),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: list.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
list[index].user?.name ?? '',
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Event.getEventById('scOUCJUs6iW7zVo4g2m8').then((value) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return ChatScreen(evento: value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ class _MyServicesScreenState extends State<MyServicesScreen> {
|
|||||||
|
|
||||||
Widget _eventList() {
|
Widget _eventList() {
|
||||||
return FutureBuilder(
|
return FutureBuilder(
|
||||||
future: getByProIdAll('aprobado', 'denegado'),
|
future: getByUserIdAll('aprobado', 'denegado'),
|
||||||
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(
|
||||||
@@ -72,7 +72,7 @@ class _MyServicesScreenState extends State<MyServicesScreen> {
|
|||||||
...eventos.map(
|
...eventos.map(
|
||||||
(event) => ListTile(
|
(event) => ListTile(
|
||||||
tileColor: event.status == 'aprobado'
|
tileColor: event.status == 'aprobado'
|
||||||
? Colors.green[100]
|
? Colors.blue[100]
|
||||||
: Colors.red[100],
|
: Colors.red[100],
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
@@ -84,7 +84,17 @@ class _MyServicesScreenState extends State<MyServicesScreen> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
leading: Text(event.range1Hour1),
|
leading: event.status == 'aprobado'
|
||||||
|
? const Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: Colors.blue,
|
||||||
|
size: 40,
|
||||||
|
)
|
||||||
|
: const Icon(
|
||||||
|
Icons.close,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 40,
|
||||||
|
),
|
||||||
title: RichText(
|
title: RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
children: [
|
children: [
|
||||||
@@ -97,10 +107,10 @@ class _MyServicesScreenState extends State<MyServicesScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: DateFormat('dd MMM', 'es')
|
text:
|
||||||
.format(DateTime.parse(event.day)),
|
'${DateFormat('dd MMM', 'es').format(DateTime.parse(event.day))} - ${event.range1Hour1}',
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.grey,
|
color: Colors.grey[600],
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ class _MyServicesProScreenState extends State<MyServicesProScreen> {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
'${DateFormat('dd MMM', 'es').format(DateTime.parse(event.day))} - ${event.range1Hour1}',
|
'${DateFormat('dd MMM', 'es').format(DateTime.parse(event.day))} - ${event.range1Hour1}',
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.grey,
|
color: Colors.grey[600],
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user