From 61d517aaeade08e84b287a1672a0237e4486276e Mon Sep 17 00:00:00 2001 From: Felipe Date: Tue, 16 Apr 2024 08:46:06 -0500 Subject: [PATCH] chat screen --- lib/blocs/chat_bloc/chat_bloc.dart | 63 ++++ lib/blocs/chat_bloc/chat_event.dart | 43 +++ lib/blocs/chat_bloc/chat_state.dart | 23 ++ lib/dependency/app_di.dart | 7 + lib/screens/chat/chat_screen.dart | 329 ++++++++++++++++++ .../service/professional_service_screen.dart | 18 +- lib/screens/service/user_service_screen.dart | 11 +- .../user/user_view_profile_screen.dart | 13 - .../chat_repository/lib/chat_repository.dart | 4 + .../lib/src/entities/chat_entity.dart | 49 +++ .../lib/src/entities/entities.dart | 2 + .../lib/src/entities/message_entity.dart | 45 +++ .../firebase_chat_repository.dart | 43 +++ packages/chat_repository/pubspec.lock | 266 ++++++++++++++ packages/chat_repository/pubspec.yaml | 25 ++ .../firebase_service_repository.dart | 3 +- pubspec.lock | 7 + pubspec.yaml | 2 + 18 files changed, 931 insertions(+), 22 deletions(-) create mode 100644 lib/blocs/chat_bloc/chat_bloc.dart create mode 100644 lib/blocs/chat_bloc/chat_event.dart create mode 100644 lib/blocs/chat_bloc/chat_state.dart create mode 100644 lib/screens/chat/chat_screen.dart create mode 100644 packages/chat_repository/lib/chat_repository.dart create mode 100644 packages/chat_repository/lib/src/entities/chat_entity.dart create mode 100644 packages/chat_repository/lib/src/entities/entities.dart create mode 100644 packages/chat_repository/lib/src/entities/message_entity.dart create mode 100644 packages/chat_repository/lib/src/repositories/firebase_chat_repository.dart create mode 100644 packages/chat_repository/pubspec.lock create mode 100644 packages/chat_repository/pubspec.yaml diff --git a/lib/blocs/chat_bloc/chat_bloc.dart b/lib/blocs/chat_bloc/chat_bloc.dart new file mode 100644 index 0000000..291cdf1 --- /dev/null +++ b/lib/blocs/chat_bloc/chat_bloc.dart @@ -0,0 +1,63 @@ +import 'dart:developer'; + +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:chat_repository/chat_repository.dart'; + +part 'chat_event.dart'; +part 'chat_state.dart'; + +class ChatBloc extends Bloc { + final FirebaseChatRepository _chatRepository; + + ChatBloc({ + required FirebaseChatRepository chatRepository, + }) : _chatRepository = chatRepository, + super(ChatInitial()) { + on(_onLoadChatEvent); + on(_onSendMessageEvent); + } + + void _onLoadChatEvent(LoadChatEvent event, Emitter emit) async { + bool autoCreate = true; + + try { + emit(ChatLoading()); + + Stream chatStream = _chatRepository.getChatById( + event.serviceId, + ); + + await for (var chat in chatStream) { + if (chat == null) { + if (autoCreate) { + chat = await _chatRepository.createNewChat( + event.serviceId, + event.userId, + event.professionalId, + ); + + autoCreate = false; + } else { + emit(ChatFailure()); + } + } else { + emit(ChatLoaded(chat: chat)); + } + } + } catch (e) { + log(e.toString()); + emit(ChatFailure()); + } + } + + void _onSendMessageEvent( + SendMessageEvent event, Emitter emit) async { + try { + await _chatRepository.sendMessage(event.serviceId, event.message); + } catch (e) { + log(e.toString()); + emit(ChatFailure()); + } + } +} diff --git a/lib/blocs/chat_bloc/chat_event.dart b/lib/blocs/chat_bloc/chat_event.dart new file mode 100644 index 0000000..86208bc --- /dev/null +++ b/lib/blocs/chat_bloc/chat_event.dart @@ -0,0 +1,43 @@ +part of 'chat_bloc.dart'; + +abstract class ChatEvent extends Equatable { + const ChatEvent(); + + @override + List get props => []; +} + +class LoadChatEvent extends ChatEvent { + final String serviceId; + final String userId; + final String professionalId; + + const LoadChatEvent({ + required this.serviceId, + required this.userId, + required this.professionalId, + }); + + @override + List get props => [ + serviceId, + userId, + professionalId, + ]; +} + +class SendMessageEvent extends ChatEvent { + final String serviceId; + final MessageEntity message; + + const SendMessageEvent({ + required this.message, + required this.serviceId, + }); + + @override + List get props => [ + serviceId, + message, + ]; +} diff --git a/lib/blocs/chat_bloc/chat_state.dart b/lib/blocs/chat_bloc/chat_state.dart new file mode 100644 index 0000000..340bbff --- /dev/null +++ b/lib/blocs/chat_bloc/chat_state.dart @@ -0,0 +1,23 @@ +part of 'chat_bloc.dart'; + +class ChatState extends Equatable { + const ChatState(); + + @override + List get props => []; +} + +class ChatInitial extends ChatState {} + +class ChatLoading extends ChatState {} + +class ChatLoaded extends ChatState { + final ChatEntity chat; + + const ChatLoaded({required this.chat}); + + @override + List get props => [chat]; +} + +class ChatFailure extends ChatState {} diff --git a/lib/dependency/app_di.dart b/lib/dependency/app_di.dart index 462773b..73a3660 100644 --- a/lib/dependency/app_di.dart +++ b/lib/dependency/app_di.dart @@ -1,9 +1,11 @@ +import 'package:chat_repository/chat_repository.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:injector/injector.dart'; import 'package:profession_repository/profession_repository.dart'; import 'package:professional_repository/professional_repository.dart'; import 'package:prosappco/blocs/auth_bloc/auth_bloc.dart'; import 'package:prosappco/blocs/authentication_bloc/authentication_bloc.dart'; +import 'package:prosappco/blocs/chat_bloc/chat_bloc.dart'; import 'package:prosappco/blocs/my_user_bloc/my_user_bloc.dart'; import 'package:prosappco/blocs/professional_bloc/professional_bloc.dart'; import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart'; @@ -35,6 +37,7 @@ class AppDI { injector.registerSingleton(() => FirebaseProfessionalRepository()); injector.registerSingleton(() => FirebaseServiceRepository()); + injector.registerSingleton(() => FirebaseChatRepository()); injector.registerSingleton((() => AuthenticationBloc(myUserRepository: injector.get()))); @@ -73,6 +76,10 @@ class AppDI { injector.get()), ); + injector.registerDependency(() => ChatBloc( + chatRepository: injector.get(), + )); + injector.registerDependency( () => ServiceBloc( serviceRepository: injector.get(), diff --git a/lib/screens/chat/chat_screen.dart b/lib/screens/chat/chat_screen.dart new file mode 100644 index 0000000..cc7916f --- /dev/null +++ b/lib/screens/chat/chat_screen.dart @@ -0,0 +1,329 @@ +import 'package:chat_repository/chat_repository.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:injector/injector.dart'; +import 'package:intl/intl.dart'; +import 'package:prosappco/blocs/chat_bloc/chat_bloc.dart'; +import 'package:prosappco/screens/user/user_view_profile_screen.dart'; +import 'package:service_repository/service_repository.dart'; +import 'package:user_repository/user_repository.dart'; + +class ChatScreen extends StatefulWidget { + final ServiceEntity service; + + const ChatScreen({super.key, required this.service}); + + @override + State createState() => _ChatScreenState(); +} + +class _ChatScreenState extends State { + late final ChatBloc chatBloc; + final TextEditingController _messageController = TextEditingController(); + final FocusNode _messageFocusNode = FocusNode(); + + @override + void initState() { + super.initState(); + + chatBloc = Injector.appInstance.get(); + + chatBloc.add(LoadChatEvent( + serviceId: widget.service.id!, + userId: widget.service.userId, + professionalId: widget.service.professionalId, + )); + } + + @override + void dispose() { + _messageController.dispose(); + _messageFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Chat'), + ), + body: BlocProvider( + create: (context) => chatBloc, + child: BlocBuilder( + builder: (context, state) { + if (state is ChatLoaded) { + return Column( + children: [ + FutureBuilder( + future: _getUserAndProfessionalInfo(widget.service), + builder: (BuildContext context, + AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else { + if (snapshot.hasError) { + return Center( + child: Text('Error inesperado: ${snapshot.error}'), + ); + } else { + final userInfo = snapshot.data![0] as MyUser; + + return Container( + padding: const EdgeInsets.symmetric(vertical: 8), + color: const Color(0xFFD6F4FF), + alignment: Alignment.topCenter, + child: ListTile( + leading: Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Colors.grey.shade300, + shape: BoxShape.circle, + image: userInfo.picture == null + ? null + : DecorationImage( + image: NetworkImage( + userInfo.picture ?? ''), + fit: BoxFit.contain, + ), + ), + child: userInfo.picture == null + ? Icon( + CupertinoIcons.person, + color: Colors.grey.shade400, + size: 40, + ) + : null, + ), + title: Text( + userInfo.name ?? '', + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + subtitle: const Text( + 'Rating: 5.0', + // _disponibilidad( + // filteredUsers[index].professionalInfo), + style: TextStyle( + fontSize: 13, + color: Colors.blue, + ), + ), + ), + ); + } + } + }, + ), + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.only(top: 10), + reverse: true, + child: Column( + children: _messagesList(state.chat.messages), + ), + ), + ), + Container( + alignment: Alignment.bottomCenter, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 15, vertical: 15), + child: Row( + children: [ + Expanded( + child: TextFormField( + focusNode: _messageFocusNode, + controller: _messageController, + 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], + ), + onFieldSubmitted: (value) async { + if (_messageController.text.isEmpty) { + return; + } + + MessageEntity message = MessageEntity( + ownerId: + FirebaseAuth.instance.currentUser!.uid, + content: _messageController.text.trim(), + createdAt: DateTime.now(), + ); + + chatBloc.add(SendMessageEvent( + serviceId: widget.service.id!, + message: message, + )); + _messageController.clear(); + _messageFocusNode.requestFocus(); + }, + ), + ), + const SizedBox(width: 12), + GestureDetector( + onTap: () async { + if (_messageController.text.isEmpty) { + return; + } + + MessageEntity message = MessageEntity( + ownerId: FirebaseAuth.instance.currentUser!.uid, + content: _messageController.text.trim(), + createdAt: DateTime.now(), + ); + + chatBloc.add(SendMessageEvent( + serviceId: widget.service.id!, + message: message, + )); + _messageController.clear(); + _messageFocusNode.requestFocus(); + }, + 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, + ), + ), + ), + ) + ], + ), + ), + ) + ], + ); + } + + return const Center( + child: CircularProgressIndicator(), + ); + }, + ), + ), + ); + } + + List _messagesList(List messages) { + return messages + .map( + (e) => e.ownerId != FirebaseAuth.instance.currentUser!.uid + ? 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.createdAt), + 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.createdAt), + style: const TextStyle( + color: Colors.grey, + fontSize: 12, + ), + ), + ), + ], + ), + ), + ) + .toList(); + } + + Future> _getUserAndProfessionalInfo( + ServiceEntity service) async { + final userRepo = FirebaseUserRepository(FirebaseAuth.instance); + + final MyUser? userInfo; + + if (FirebaseAuth.instance.currentUser!.uid == service.userId) { + userInfo = await userRepo.getMyUser(service.userId); + } else { + userInfo = await userRepo.getMyUser(service.professionalId); + } + + return [userInfo]; + } +} diff --git a/lib/screens/service/professional_service_screen.dart b/lib/screens/service/professional_service_screen.dart index ed65892..f57deea 100644 --- a/lib/screens/service/professional_service_screen.dart +++ b/lib/screens/service/professional_service_screen.dart @@ -8,6 +8,7 @@ import 'package:intl/intl.dart'; import 'package:professional_repository/professional_repository.dart'; import 'package:prosappco/blocs/service_bloc/service_bloc.dart'; import 'package:prosappco/components/general_secondary_button.dart'; +import 'package:prosappco/screens/chat/chat_screen.dart'; import 'package:service_repository/service_repository.dart'; import 'package:setting_repository/setting_repository.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -55,8 +56,7 @@ class _ProfessionalServiceScreenState extends State { final service = state.service; return FutureBuilder( future: _getUserAndProfessionalInfo(service), - builder: (BuildContext context, - AsyncSnapshot> snapshot) { + builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else { @@ -274,7 +274,16 @@ class _ProfessionalServiceScreenState extends State { ), ), ElevatedButton( - onPressed: () {}, + onPressed: () { + if (service.id != null) { + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ChatScreen(service: service), + ), + ); + } + }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, @@ -661,8 +670,7 @@ class _ProfessionalServiceScreenState extends State { return '\$${formatter.format(number)}'; } - Future> _getUserAndProfessionalInfo( - ServiceEntity service) async { + Future> _getUserAndProfessionalInfo(ServiceEntity service) async { final userRepo = FirebaseUserRepository(FirebaseAuth.instance); final userInfo = await userRepo.getMyUser(service.userId); diff --git a/lib/screens/service/user_service_screen.dart b/lib/screens/service/user_service_screen.dart index d000188..1ebf7a8 100644 --- a/lib/screens/service/user_service_screen.dart +++ b/lib/screens/service/user_service_screen.dart @@ -7,6 +7,7 @@ import 'package:injector/injector.dart'; import 'package:intl/intl.dart'; import 'package:professional_repository/professional_repository.dart'; import 'package:prosappco/blocs/service_bloc/service_bloc.dart'; +import 'package:prosappco/screens/chat/chat_screen.dart'; import 'package:prosappco/components/general_secondary_button.dart'; import 'package:service_repository/service_repository.dart'; import 'package:setting_repository/setting_repository.dart'; @@ -238,7 +239,6 @@ class _UserServiceScreenState extends State { customMapButton(service), - // ListTile( // leading: const Icon(Icons.near_me), // title: Text( @@ -423,7 +423,14 @@ class _UserServiceScreenState extends State { ), ), ElevatedButton( - onPressed: () {}, + onPressed: () { + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ChatScreen(service: service), + ), + ); + }, style: ElevatedButton.styleFrom( foregroundColor: const Color(0xFF2BA4EC), backgroundColor: Colors.white, diff --git a/lib/screens/user/user_view_profile_screen.dart b/lib/screens/user/user_view_profile_screen.dart index 4f857e0..101cf87 100644 --- a/lib/screens/user/user_view_profile_screen.dart +++ b/lib/screens/user/user_view_profile_screen.dart @@ -27,19 +27,6 @@ class UserViewProfileScreen extends StatelessWidget { ], ), ); - - // Container( - // decoration: BoxDecoration( - // gradient: LinearGradient( - // colors: [ - // Colors.blue.withOpacity(1), - // Colors.blue.withOpacity(0), - // Colors.blue.withOpacity(0), - // ], - // begin: Alignment.bottomCenter, - // end: Alignment.topCenter, - // ), - // ), } Stack buildTop() { diff --git a/packages/chat_repository/lib/chat_repository.dart b/packages/chat_repository/lib/chat_repository.dart new file mode 100644 index 0000000..8cbec77 --- /dev/null +++ b/packages/chat_repository/lib/chat_repository.dart @@ -0,0 +1,4 @@ +library chat_repository; + +export 'src/entities/entities.dart'; +export 'src/repositories/firebase_chat_repository.dart'; diff --git a/packages/chat_repository/lib/src/entities/chat_entity.dart b/packages/chat_repository/lib/src/entities/chat_entity.dart new file mode 100644 index 0000000..56b78cf --- /dev/null +++ b/packages/chat_repository/lib/src/entities/chat_entity.dart @@ -0,0 +1,49 @@ +import 'package:chat_repository/src/entities/entities.dart'; +import 'package:equatable/equatable.dart'; + +class ChatEntity extends Equatable { + final String? id; + final String userId; + final String professionalId; + final List messages; + + const ChatEntity({ + required this.id, + required this.userId, + required this.professionalId, + required this.messages, + }); + + static ChatEntity fromDocument(Map doc) { + return ChatEntity( + id: doc['id'] as String, + userId: doc['user_id'] as String, + professionalId: doc['professional_id'] as String, + messages: (doc['messages'] as List) + .map((e) => MessageEntity.fromDocument(e as Map)) + .toList(), + ); + } + + Map toDocument() { + return { + 'id': id, + 'user_id': userId, + 'professional_id': professionalId, + 'messages': messages.map((e) => e.toDocument()).toList(), + }; + } + + @override + List get props => [id, userId, professionalId, messages]; + + @override + String toString() { + return '''ChatEntity{ + id: $id, + userId: $userId, + professionalId: $professionalId, + messages: $messages + }'''; + } +} diff --git a/packages/chat_repository/lib/src/entities/entities.dart b/packages/chat_repository/lib/src/entities/entities.dart new file mode 100644 index 0000000..d9e4781 --- /dev/null +++ b/packages/chat_repository/lib/src/entities/entities.dart @@ -0,0 +1,2 @@ +export '/src/entities/chat_entity.dart'; +export '/src/entities/message_entity.dart'; diff --git a/packages/chat_repository/lib/src/entities/message_entity.dart b/packages/chat_repository/lib/src/entities/message_entity.dart new file mode 100644 index 0000000..ba31b77 --- /dev/null +++ b/packages/chat_repository/lib/src/entities/message_entity.dart @@ -0,0 +1,45 @@ +import 'package:equatable/equatable.dart'; + +class MessageEntity extends Equatable { + final String ownerId; + final String content; + final DateTime createdAt; + + const MessageEntity({ + required this.ownerId, + required this.content, + required this.createdAt, + }); + + static MessageEntity fromDocument(Map doc) { + return MessageEntity( + ownerId: doc['owner_id'] as String, + content: doc['content'] as String, + createdAt: DateTime.parse(doc['created_at'] as String), + ); + } + + Map toDocument() { + return { + 'owner_id': ownerId, + 'content': content, + 'created_at': createdAt.toIso8601String(), + }; + } + + @override + List get props => [ + ownerId, + content, + createdAt, + ]; + + @override + String toString() { + return '''MessageEntity{ + ownerId: $ownerId, + content: $content, + createdAt: $createdAt + }'''; + } +} diff --git a/packages/chat_repository/lib/src/repositories/firebase_chat_repository.dart b/packages/chat_repository/lib/src/repositories/firebase_chat_repository.dart new file mode 100644 index 0000000..9fdd213 --- /dev/null +++ b/packages/chat_repository/lib/src/repositories/firebase_chat_repository.dart @@ -0,0 +1,43 @@ +import 'dart:developer'; + +import 'package:chat_repository/chat_repository.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; + +class FirebaseChatRepository { + final chatCollection = FirebaseFirestore.instance.collection('chats'); + + Stream getChatById(String chatId) { + return chatCollection.doc(chatId).snapshots().map((snapshot) { + try { + if (snapshot.exists) { + return ChatEntity.fromDocument(snapshot.data()!); + } else { + return null; + } + } catch (e) { + log(e.toString()); + return null; + } + }); + } + + Future createNewChat( + String chatId, String userId, String professionalId) async { + ChatEntity chat = ChatEntity( + id: chatId, + userId: userId, + professionalId: professionalId, + messages: const [], + ); + + await chatCollection.doc(chatId).set(chat.toDocument()); + + return chat; + } + + sendMessage(String chatId, MessageEntity message) { + chatCollection.doc(chatId).update({ + 'messages': FieldValue.arrayUnion([message.toDocument()]) + }); + } +} diff --git a/packages/chat_repository/pubspec.lock b/packages/chat_repository/pubspec.lock new file mode 100644 index 0000000..cb1d0da --- /dev/null +++ b/packages/chat_repository/pubspec.lock @@ -0,0 +1,266 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + url: "https://pub.dev" + source: hosted + version: "1.3.25" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + cloud_firestore: + dependency: "direct main" + description: + name: cloud_firestore + sha256: "31cfa4d65d6e9ea837234fffe121304034c30c9214c06207b4a35867e3757900" + url: "https://pub.dev" + source: hosted + version: "4.15.8" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + sha256: a0097a26569b015faf8142e159e855241609ea9a1738b5fd1c40bfe8411b41a0 + url: "https://pub.dev" + source: hosted + version: "6.1.9" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + sha256: ed680ece29a5750985119c09cdc276b460c3a2fa80e8c12f9b7241f6b4a7ca16 + url: "https://pub.dev" + source: hosted + version: "3.10.8" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + url: "https://pub.dev" + source: hosted + version: "2.27.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63 + url: "https://pub.dev" + source: hosted + version: "5.0.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + url: "https://pub.dev" + source: hosted + version: "2.11.5" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + url: "https://pub.dev" + source: hosted + version: "1.10.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + url: "https://pub.dev" + source: hosted + version: "0.3.0" +sdks: + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.3.0" diff --git a/packages/chat_repository/pubspec.yaml b/packages/chat_repository/pubspec.yaml new file mode 100644 index 0000000..035a2c4 --- /dev/null +++ b/packages/chat_repository/pubspec.yaml @@ -0,0 +1,25 @@ +name: chat_repository +description: Dart package for the chat repository. +publish_to: 'none' + +version: 1.0.11+11 + +environment: + sdk: ">=2.19.3 <3.0.0" + +dependencies: + flutter: + sdk: flutter + equatable: ^2.0.5 + + # Firebase + cloud_firestore: ^4.15.4 + firebase_core: ^2.25.4 + +dev_dependencies: + flutter_lints: ^2.0.0 + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true \ No newline at end of file diff --git a/packages/service_repository/lib/src/repositories/firebase_service_repository.dart b/packages/service_repository/lib/src/repositories/firebase_service_repository.dart index feee3ac..7c84433 100644 --- a/packages/service_repository/lib/src/repositories/firebase_service_repository.dart +++ b/packages/service_repository/lib/src/repositories/firebase_service_repository.dart @@ -2,8 +2,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:service_repository/service_repository.dart'; class FirebaseServiceRepository { - final serviceCollection = - FirebaseFirestore.instance.collection('services v2'); + final serviceCollection = FirebaseFirestore.instance.collection('services'); Future createService(ServiceEntity entity) async { DocumentReference> docRef = diff --git a/pubspec.lock b/pubspec.lock index 0d31cfa..f2e02c2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -89,6 +89,13 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + chat_repository: + dependency: "direct main" + description: + path: "packages/chat_repository" + relative: true + source: path + version: "1.0.11+11" city_repository: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 145c6f1..e47d3da 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -56,6 +56,8 @@ dependencies: path: packages/user_repository city_repository: path: packages/city_repository + chat_repository: + path: packages/chat_repository setting_repository: path: packages/setting_repository professional_repository: