This commit is contained in:
Felipe
2024-03-15 16:55:01 -05:00
parent a3c50cf2c8
commit e5a8221edf
9 changed files with 337 additions and 115 deletions
@@ -39,25 +39,43 @@ class ProfessionalBloc extends Bloc<ProfessionalEvent, ProfessionalState> {
on<SendProfessionalToReviewEvent>((event, emit) async {
final myUser = await _userRepository.lastUser();
if (myUser == null) return;
await _professionalRepository.saveProfessionalInfo(ProfessionalEntity(
id: event.id,
identification: event.identification,
identificationPicture: event.identificationPicture,
address: '',
profession: event.profession,
specializations: event.specializations,
specializationsPictures: event.specializationsPictures,
certificatePicture: event.certificatePicture,
latitude: '',
longitude: '',
rate: '',
location: '',
schedules: Schedules.empty,
paymentMethods: PaymentMethodEntity.empty,
));
try {
final identificationPdfUrl = await _professionalRepository
.uploadPdfCedula(event.identificationPicture, myUser.id);
_userRepository
.updateUserInfo(myUser.copyWith(proState: ProState.pending));
final certificatePdfUrl = await _professionalRepository
.uploadPdfCertificado(event.certificatePicture, myUser.id);
List<String> specializationsPdfUrls = [];
if (event.specializationsPictures.isNotEmpty) {
specializationsPdfUrls =
await _professionalRepository.uploadPdfsEspecializaciones(
event.specializationsPictures, myUser.id);
} else {
specializationsPdfUrls = [];
}
await _professionalRepository.saveProfessionalInfo(ProfessionalEntity(
id: event.id,
identification: event.identification,
identificationPicture: identificationPdfUrl,
address: '',
profession: event.profession,
specializations: event.specializations,
specializationsPictures: specializationsPdfUrls,
certificatePicture: certificatePdfUrl,
latitude: '',
longitude: '',
rate: '',
location: '',
schedules: Schedules.empty,
paymentMethods: PaymentMethodEntity.empty,
));
} catch (e) {
log('error acceso a pro ${e.toString()}');
}
// _userRepository
// .updateUserInfo(myUser.copyWith(proState: ProState.pending));
});
}
}
+1 -5
View File
@@ -7,19 +7,15 @@ part 'profile_state.dart';
class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
final UserRepository _userRepository;
// final AuthBloc _authBloc; // lo nuevo
ProfileBloc({
required UserRepository userRepository,
// required AuthBloc authBloc
}) : _userRepository = userRepository,
// _authBloc = authBloc,
super(UpdateUserInfoInitial()) {
on<UpdateUserInfo>(_onUpdateUserInfo);
}
void _onUpdateUserInfo(
UpdateUserInfo event, Emitter<ProfileState> emit) async {
void _onUpdateUserInfo(UpdateUserInfo event, Emitter<ProfileState> emit) async {
emit(UpdateUserInfoLoading());
try {
final userImageUrl = event.filePicture != null
+4 -3
View File
@@ -20,15 +20,16 @@ class GeneralDrawerHeader extends StatelessWidget {
CupertinoPageRoute(
builder: (BuildContext context) {
return const ProfileScreen();
// return const CityScreen();
},
),
);
},
title: Text(user.name ?? '',
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontWeight: FontWeight.bold)),
subtitle:
Text(user.drawerLabel, style: const TextStyle(fontSize: 12)),
subtitle: Text(user.drawerLabel,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 12)),
leading: pictureWidget(user.picture, context),
trailing:
const Icon(Icons.keyboard_arrow_right, color: Colors.black),
@@ -29,7 +29,6 @@ class _ProfessionScreenState extends State<ProfessionScreen> {
void _loadProfessions() {
professionRepository.getProfessions().then((Professions element) {
setState(() {
log(element.toString());
_professions = element.professions;
_filteredProfessions = _professions;
_isLoading = false;
@@ -7,7 +7,10 @@ import 'package:image_picker/image_picker.dart';
import 'package:prosappco/blocs/auth_bloc/auth_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/profile_bloc/profile_bloc.dart';
import 'package:prosappco/screens/profession/profession_screen.dart';
import 'package:user_repository/user_repository.dart';
import 'package:file_picker/file_picker.dart';
class ProfessionalFormScreen extends StatefulWidget {
const ProfessionalFormScreen({super.key});
@@ -19,10 +22,13 @@ class ProfessionalFormScreen extends StatefulWidget {
class _ProfessionalFormScreenState extends State<ProfessionalFormScreen> {
final TextEditingController _cedulaController = TextEditingController();
final TextEditingController _professionController = TextEditingController();
final TextEditingController _controller = TextEditingController();
final TextEditingController _specialityController = TextEditingController();
final List<String> _items = [];
XFile? _imageFile;
PlatformFile? _cedulaPdfFile;
PlatformFile? _certificadoPdfFile;
List<PlatformFile>? _especializacionesPdfFiles = [];
late final AuthBloc authBloc;
@@ -83,6 +89,19 @@ class _ProfessionalFormScreenState extends State<ProfessionalFormScreen> {
return null;
},
),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: _pickCedulaPDF,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Cargar pdf de la cedula'),
_cedulaPdfFile != null
? const Icon(Icons.check)
: const Icon(Icons.file_upload_outlined),
],
),
),
const SizedBox(height: 20.0),
TextFormField(
controller: _professionController,
@@ -123,9 +142,22 @@ class _ProfessionalFormScreenState extends State<ProfessionalFormScreen> {
return null;
},
),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: _pickCertificadoPDF,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Cargar pdf del certificado'),
_certificadoPdfFile != null
? const Icon(Icons.check)
: const Icon(Icons.file_upload_outlined),
],
),
),
const SizedBox(height: 20.0),
TextField(
controller: _controller,
controller: _specialityController,
onSubmitted: (value) {
_addItemToList();
},
@@ -151,24 +183,140 @@ class _ProfessionalFormScreenState extends State<ProfessionalFormScreen> {
),
),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: _pickEspecializacionesPDF,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Expanded(
child: Text(
'Cargar pdfs de tus especializaciones',
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
),
_especializacionesPdfFiles?.isNotEmpty == true
? const Icon(Icons.check)
: const Icon(Icons.file_upload_outlined),
],
),
),
const SizedBox(height: 10.0),
Wrap(
spacing: 8.0,
runSpacing: 4.0,
children: _items
.map((item) => Chip(
label: Text(item),
backgroundColor: Theme.of(context).primaryColor,
labelStyle:
const TextStyle(color: Colors.white),
deleteIconColor: Colors.white,
backgroundColor:
Theme.of(context).colorScheme.tertiary,
labelStyle: const TextStyle(color: Colors.blue),
deleteIconColor: Colors.blue,
onDeleted: () {
_removeItemFromList(item);
},
shape: RoundedRectangleBorder(
side: const BorderSide(
color: Colors.blue, width: 0.3),
borderRadius: BorderRadius.circular(8),
),
))
.toList(),
),
const SizedBox(height: 60.0),
saveButton(state, context),
const SizedBox(height: 40),
ElevatedButton(
onPressed: () {
final userId =
context.read<MyUserBloc>().state.user!.id;
final String? cedulaPdfPath = _cedulaPdfFile?.path;
final String? certificadoPdfPath =
_certificadoPdfFile?.path;
final List<String> especializacionesPdfPaths =
_especializacionesPdfFiles
?.map((file) => file.path)
.where((file) => file != null)
.map((e) => e!)
.toList() ??
[];
if (_cedulaController.text.isEmpty ||
_professionController.text.isEmpty) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Llena los campos de cedula y profesión')));
return;
}
if (cedulaPdfPath == null) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Carga el pdf de tu cedula')));
return;
}
if (certificadoPdfPath == null) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
'Carga el pdf de tu certificado profesional')));
return;
}
context
.read<ProfessionalBloc>()
.add(SendProfessionalToReviewEvent(
id: userId,
identification: _cedulaController.text,
identificationPicture: cedulaPdfPath,
profession: _professionController.text,
certificatePicture: certificadoPdfPath,
specializations: _items,
specializationsPictures:
especializacionesPdfPaths,
));
final myUser =
state.user!.copyWith(proState: ProState.pending);
context.read<ProfileBloc>().add(UpdateUserInfo(
myUser: myUser, filePicture: _imageFile?.path));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Información enviada a revisión')),
);
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(vertical: 5),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
shadowColor: Colors.grey,
// elevation: 0,
),
child: Container(
constraints: const BoxConstraints(
maxWidth: 300.0, minHeight: 50.0),
alignment: Alignment.center,
child: const Text(
'Enviar a revisión',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 20),
],
),
),
@@ -181,10 +329,10 @@ class _ProfessionalFormScreenState extends State<ProfessionalFormScreen> {
void _addItemToList() {
setState(() {
String newItem = _controller.text.trim();
String newItem = _specialityController.text.trim();
if (newItem.isNotEmpty) {
_items.add(newItem);
_controller.clear();
_specialityController.clear();
}
});
}
@@ -195,81 +343,44 @@ class _ProfessionalFormScreenState extends State<ProfessionalFormScreen> {
});
}
Widget saveButton(MyUserState state, BuildContext context) {
return ElevatedButton(
onPressed: () {
final userId = context.read<MyUserBloc>().state.user!.id;
context.read<ProfessionalBloc>().add(SendProfessionalToReviewEvent(
id: userId,
identification: _cedulaController.text,
identificationPicture: _cedulaController.text,
profession: _professionController.text,
certificatePicture: _professionController.text,
specializations: _items,
specializationsPictures: _items,
));
// if (isLoading) {
// return;
// }
// if (_nameController.text.isEmpty) {
// ScaffoldMessenger.of(context).clearSnackBars();
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(content: Text('Por favor, ingrese su nombre')));
// return;
// }
// if (_cityController.text.isEmpty) {
// ScaffoldMessenger.of(context).clearSnackBars();
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(content: Text('Por favor, ingrese su ciudad')));
// }
// final myUser = state.user!.copyWith(
// name: _nameController.text,
// city: _cityController.text,
// nickname: _nameController.text.trim().toLowerCase(),
// email: _emailController.text,
// phone: _phoneController.text,
// birthday: _birthdayController.text,
// gender: _genderController.text,
// );
// context
// .read<ProfileBloc>()
// .add(UpdateUserInfo(myUser: myUser, filePicture: _imageFile?.path));
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Información actualizada...')),
);
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(vertical: 5),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
shadowColor: Colors.grey,
// elevation: 0,
),
child: Container(
constraints: const BoxConstraints(maxWidth: 300.0, minHeight: 50.0),
alignment: Alignment.center,
child: const Text(
'Actualizar',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Future<void> _pickCedulaPDF() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['pdf'],
);
if (result != null) {
setState(() {
_cedulaPdfFile = result.files.first;
});
}
}
Future<void> _pickCertificadoPDF() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['pdf'],
);
if (result != null) {
setState(() {
_certificadoPdfFile = result.files.first;
});
}
}
Future<void> _pickEspecializacionesPDF() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['pdf'],
allowMultiple: true,
);
if (result != null) {
setState(() {
_especializacionesPdfFiles = result.files;
});
}
}
Widget pictureWidget(MyUserState state, BuildContext context) {
@@ -1,11 +1,12 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:professional_repository/professional_repository.dart';
import 'package:firebase_storage/firebase_storage.dart';
class FirebaseProfessionalRepository {
bool isProModeActive = false;
final professionalCollection =
FirebaseFirestore.instance.collection('professional_info');
@@ -28,4 +29,52 @@ class FirebaseProfessionalRepository {
Future<void> saveProfessionalInfo(ProfessionalEntity entity) async {
await professionalCollection.doc(entity.id).set(entity.toJson());
}
Future<String> uploadPdfCedula(String file, String userId) async {
try {
File pdfFile = File(file);
Reference firebaseStoreRef =
FirebaseStorage.instance.ref().child('$userId/PDF/${userId}_cedula');
await firebaseStoreRef.putFile(pdfFile);
String url = await firebaseStoreRef.getDownloadURL();
return url;
} catch (e) {
log(e.toString());
rethrow;
}
}
Future<String> uploadPdfCertificado(String file, String userId) async {
try {
File pdfFile = File(file);
Reference firebaseStoreRef = FirebaseStorage.instance
.ref()
.child('$userId/PDF/${userId}_certificado');
await firebaseStoreRef.putFile(pdfFile);
String url = await firebaseStoreRef.getDownloadURL();
return url;
} catch (e) {
log(e.toString());
rethrow;
}
}
Future<List<String>> uploadPdfsEspecializaciones(
List<String> files, String userId) async {
try {
List<String> urls = [];
for (String file in files) {
File pdfFile = File(file);
Reference firebaseStoreRef = FirebaseStorage.instance.ref().child(
'$userId/PDF/${userId}_${DateTime.now().millisecondsSinceEpoch}_especializacion');
await firebaseStoreRef.putFile(pdfFile);
String url = await firebaseStoreRef.getDownloadURL();
urls.add(url);
}
return urls;
} catch (e) {
log(e.toString());
rethrow;
}
}
}
@@ -113,6 +113,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.11.5"
firebase_storage:
dependency: "direct main"
description:
name: firebase_storage
sha256: ce1b0efe8dc111058c5f079b2f2ce84906d030d0fd2eef70c42ca1253c67039a
url: "https://pub.dev"
source: hosted
version: "11.6.9"
firebase_storage_platform_interface:
dependency: transitive
description:
name: firebase_storage_platform_interface
sha256: "4a2b64d4dac096390a0b7f2e7b6d086d0546c4a1bf7ee3fc4b5ae4cc41005c46"
url: "https://pub.dev"
source: hosted
version: "5.1.12"
firebase_storage_web:
dependency: transitive
description:
name: firebase_storage_web
sha256: "4153814db8d59138e816d9f016736e4095c45675a2c18f2868d11ffd8cc6a4ca"
url: "https://pub.dev"
source: hosted
version: "3.7.3"
flutter:
dependency: "direct main"
description: flutter
@@ -136,6 +160,22 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: transitive
description:
name: http
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
url: "https://pub.dev"
source: hosted
version: "1.2.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
intl:
dependency: "direct main"
description:
@@ -253,6 +293,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.1"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
vector_math:
dependency: transitive
description:
@@ -14,6 +14,7 @@ dependencies:
# Firebase
cloud_firestore: ^4.15.4
firebase_storage: ^11.6.5
firebase_core: ^2.25.4
intl: ^0.18.1
@@ -367,8 +367,7 @@ class FirebaseUserRepository implements UserRepository {
Future<String> uploadPicture(String file, String userId) async {
try {
File imageFile = File(file);
Reference firebaseStoreRef =
FirebaseStorage.instance.ref().child('$userId/PP/${userId}_lead');
Reference firebaseStoreRef = FirebaseStorage.instance.ref().child('$userId/PP/${userId}_lead');
await firebaseStoreRef.putFile(imageFile);
String url = await firebaseStoreRef.getDownloadURL();
return url;