imagenes falta especializaciones
This commit is contained in:
@@ -27,6 +27,6 @@ subprojects {
|
|||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/foundation.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:prosappco/src/authentication/authentication_repository.dart';
|
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||||
@@ -8,7 +9,9 @@ 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/configuracion.dart';
|
import 'package:prosappco/src/screens/configuracion.dart';
|
||||||
import 'package:prosappco/src/screens/messages_user.dart';
|
import 'package:prosappco/src/screens/messages_user.dart';
|
||||||
|
import 'package:prosappco/src/screens/professional_profile_web.dart';
|
||||||
import 'package:prosappco/src/screens/profile.dart';
|
import 'package:prosappco/src/screens/profile.dart';
|
||||||
|
import 'package:prosappco/src/screens/profile_web.dart';
|
||||||
import 'package:prosappco/src/screens/reputation.dart';
|
import 'package:prosappco/src/screens/reputation.dart';
|
||||||
import 'package:prosappco/src/screens/support.dart';
|
import 'package:prosappco/src/screens/support.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -53,14 +56,25 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
if (kIsWeb) {
|
||||||
context,
|
Navigator.push(
|
||||||
CupertinoPageRoute(
|
context,
|
||||||
builder: (BuildContext context) {
|
CupertinoPageRoute(
|
||||||
return const ProfileScreen();
|
builder: (BuildContext context) {
|
||||||
},
|
return const ProfileWebScreen();
|
||||||
),
|
},
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const ProfileScreen();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
title: Text(user?.name ?? '',
|
title: Text(user?.name ?? '',
|
||||||
style: const TextStyle(fontWeight: FontWeight.bold)),
|
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
@@ -129,14 +143,25 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
if (kIsWeb) {
|
||||||
context,
|
Navigator.push(
|
||||||
CupertinoPageRoute(
|
context,
|
||||||
builder: (BuildContext context) {
|
CupertinoPageRoute(
|
||||||
return const ProfileScreen();
|
builder: (BuildContext context) {
|
||||||
},
|
return const ProfileWebScreen();
|
||||||
),
|
},
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const ProfileScreen();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
leading: const Icon(
|
leading: const Icon(
|
||||||
Icons.person_outline,
|
Icons.person_outline,
|
||||||
@@ -347,7 +372,16 @@ class _DrawerMenuState extends State<DrawerMenu> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (user?.state == 'pendiente' || user?.state == null) {
|
if (user?.state == 'pendiente' || user?.state == null) {
|
||||||
Navigator.pushNamed(context, '/profesionalProfile');
|
if (kIsWeb) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const ProfessionalProfileWebScreen()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.pushNamed(context, '/profesionalProfile');
|
||||||
|
}
|
||||||
} else if (user?.state == 'revision') {
|
} else if (user?.state == 'revision') {
|
||||||
Navigator.pushNamed(context, '/profesionalRevision');
|
Navigator.pushNamed(context, '/profesionalRevision');
|
||||||
} else if (user?.state == 'activo') {
|
} else if (user?.state == 'activo') {
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
|
|
||||||
|
const double photoSize = 100;
|
||||||
|
const double iconSize = 55;
|
||||||
|
|
||||||
|
class ReferencePhotoWeb extends StatelessWidget {
|
||||||
|
Reference? ref;
|
||||||
|
double size;
|
||||||
|
double sizeIcon;
|
||||||
|
double sizeCircle;
|
||||||
|
|
||||||
|
ReferencePhotoWeb({
|
||||||
|
super.key,
|
||||||
|
required this.ref,
|
||||||
|
this.sizeIcon = iconSize,
|
||||||
|
this.size = photoSize,
|
||||||
|
this.sizeCircle = photoSize,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<Widget> downloadImage() async {
|
||||||
|
try {
|
||||||
|
if (ref != null) {
|
||||||
|
final imageData = await ref!.getData();
|
||||||
|
if (imageData != null) {
|
||||||
|
return ClipOval(
|
||||||
|
child: Image.memory(
|
||||||
|
imageData,
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ignore: empty_catches
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
return DefaultPhotoWeb(
|
||||||
|
sizeDefault: sizeCircle,
|
||||||
|
iconDefault: sizeIcon,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<Widget>(
|
||||||
|
future: downloadImage(),
|
||||||
|
builder: (BuildContext context, AsyncSnapshot<Widget> snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
// mientras la llamada asíncrona está en proceso, muestra un mensaje de carga
|
||||||
|
return SizedBox(
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
child: const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (snapshot.connectionState == ConnectionState.done &&
|
||||||
|
snapshot.hasData) {
|
||||||
|
return snapshot.data!;
|
||||||
|
} else {
|
||||||
|
return DefaultPhotoWeb();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultPhotoWeb extends StatelessWidget {
|
||||||
|
double sizeDefault;
|
||||||
|
double iconDefault;
|
||||||
|
|
||||||
|
DefaultPhotoWeb({
|
||||||
|
super.key,
|
||||||
|
this.sizeDefault = photoSize,
|
||||||
|
this.iconDefault = iconSize,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: sizeDefault,
|
||||||
|
height: sizeDefault,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFF2BA4EC),
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.person,
|
||||||
|
color: const Color.fromARGB(255, 255, 255, 255),
|
||||||
|
size: iconDefault,
|
||||||
|
),
|
||||||
|
).animate().shake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LocalPhotoWeb extends StatelessWidget {
|
||||||
|
Uint8List? file;
|
||||||
|
LocalPhotoWeb({super.key, required this.file});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (file == null) {
|
||||||
|
return DefaultPhotoWeb();
|
||||||
|
} else {
|
||||||
|
return ClipOval(
|
||||||
|
child: Image.memory(
|
||||||
|
file!,
|
||||||
|
width: photoSize,
|
||||||
|
height: photoSize,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+170
-77
@@ -1,4 +1,5 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:intl_phone_field/intl_phone_field.dart';
|
import 'package:intl_phone_field/intl_phone_field.dart';
|
||||||
@@ -33,87 +34,179 @@ class _NewNumberScreenState extends State<NewNumberScreen> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
iconTheme: const IconThemeData(
|
iconTheme: const IconThemeData(
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
title: const Text(
|
|
||||||
'Añadir numero',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
title: const Text(
|
||||||
),
|
'Añadir numero',
|
||||||
body: Container(
|
style: TextStyle(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 20),
|
color: Colors.black,
|
||||||
margin: const EdgeInsets.only(top: 30, left: 50, right: 50),
|
|
||||||
child: Column(children: [
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.only(bottom: 5),
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.topLeft,
|
|
||||||
child: Text('Numero de celular',
|
|
||||||
style: TextStyle(fontSize: 18.0, color: Color(0xFF65676B))),
|
|
||||||
)),
|
|
||||||
Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 5),
|
|
||||||
child: IntlPhoneField(
|
|
||||||
controller: controller.newPhoneNo,
|
|
||||||
initialCountryCode: 'CO',
|
|
||||||
onChanged: (newPhoneNo) {
|
|
||||||
completePhoneNumber = newPhoneNo.completeNumber;
|
|
||||||
},
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(color: Color(0xFFECECEC)),
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(50),
|
|
||||||
)),
|
|
||||||
errorBorder: OutlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
BorderSide(color: Color.fromARGB(255, 184, 0, 0)),
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(50),
|
|
||||||
)),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(color: Color(0xFFECECEC)),
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(50),
|
|
||||||
)),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(color: Color(0xFFECECEC)),
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(50),
|
|
||||||
)),
|
|
||||||
fillColor: Color.fromARGB(255, 239, 239, 239),
|
|
||||||
filled: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Padding(
|
),
|
||||||
padding: EdgeInsets.only(bottom: 30),
|
body: !kIsWeb
|
||||||
child: Text('Un código será enviado a este numero de celular.',
|
? Container(
|
||||||
textAlign: TextAlign.center,
|
padding:
|
||||||
style: TextStyle(fontSize: 13.0, color: Color(0xFF65676B))),
|
const EdgeInsets.symmetric(horizontal: 0, vertical: 20),
|
||||||
),
|
margin: const EdgeInsets.only(top: 30, left: 50, right: 50),
|
||||||
Padding(
|
child: Column(
|
||||||
padding: const EdgeInsets.only(bottom: 30),
|
children: [
|
||||||
child: Center(
|
const Padding(
|
||||||
child: PrimaryButtom(
|
padding: EdgeInsets.only(bottom: 5),
|
||||||
onPressed: () {
|
child: Align(
|
||||||
controller
|
alignment: Alignment.topLeft,
|
||||||
.updatePhoneNumber(completePhoneNumber.toString());
|
child: Text('Numero de celular',
|
||||||
},
|
style: TextStyle(
|
||||||
label: 'Enviar código')),
|
fontSize: 18.0, color: Color(0xFF65676B))),
|
||||||
),
|
)),
|
||||||
]),
|
Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 5),
|
||||||
|
child: IntlPhoneField(
|
||||||
|
controller: controller.newPhoneNo,
|
||||||
|
initialCountryCode: 'CO',
|
||||||
|
onChanged: (newPhoneNo) {
|
||||||
|
completePhoneNumber = newPhoneNo.completeNumber;
|
||||||
|
},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xFFECECEC)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
errorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color.fromARGB(255, 184, 0, 0)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xFFECECEC)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xFFECECEC)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
fillColor: Color.fromARGB(255, 239, 239, 239),
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 30),
|
||||||
|
child: Text(
|
||||||
|
'Un código será enviado a este numero de celular.',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13.0, color: Color(0xFF65676B))),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 30),
|
||||||
|
child: Center(
|
||||||
|
child: PrimaryButtom(
|
||||||
|
onPressed: () {
|
||||||
|
controller.updatePhoneNumber(
|
||||||
|
completePhoneNumber.toString());
|
||||||
|
},
|
||||||
|
label: 'Enviar código'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Center(
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 0, vertical: 20),
|
||||||
|
width: 400,
|
||||||
|
margin: const EdgeInsets.only(top: 30, left: 50, right: 50),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 5),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
child: Text('Numero de celular',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.0, color: Color(0xFF65676B))),
|
||||||
|
)),
|
||||||
|
Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 5),
|
||||||
|
child: IntlPhoneField(
|
||||||
|
controller: controller.newPhoneNo,
|
||||||
|
initialCountryCode: 'CO',
|
||||||
|
onChanged: (newPhoneNo) {
|
||||||
|
completePhoneNumber = newPhoneNo.completeNumber;
|
||||||
|
},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xFFECECEC)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
errorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color.fromARGB(255, 184, 0, 0)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xFFECECEC)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: Color(0xFFECECEC)),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(50),
|
||||||
|
)),
|
||||||
|
fillColor: Color.fromARGB(255, 239, 239, 239),
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 30),
|
||||||
|
child: Text(
|
||||||
|
'Un código será enviado a este numero de celular.',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13.0, color: Color(0xFF65676B))),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 30),
|
||||||
|
child: Center(
|
||||||
|
child: PrimaryButtom(
|
||||||
|
onPressed: () {
|
||||||
|
controller.updatePhoneNumber(
|
||||||
|
completePhoneNumber.toString());
|
||||||
|
},
|
||||||
|
label: 'Enviar código'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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_auth/firebase_auth.dart';
|
||||||
import 'package:firebase_storage/firebase_storage.dart';
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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';
|
||||||
@@ -160,7 +161,7 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
child: ListBody(
|
child: ListBody(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Text(
|
child: const Text(
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
"Tomar foto",
|
"Tomar foto",
|
||||||
style: TextStyle(color: Color(0xFF2BA4EC)),
|
style: TextStyle(color: Color(0xFF2BA4EC)),
|
||||||
@@ -173,9 +174,9 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Divider(color: Colors.black54),
|
const Divider(color: Colors.black54),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Text(
|
child: const Text(
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
"Abrir Galería",
|
"Abrir Galería",
|
||||||
style: TextStyle(color: Color(0xFF2BA4EC)),
|
style: TextStyle(color: Color(0xFF2BA4EC)),
|
||||||
@@ -428,11 +429,11 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
_showChoiceDialog(context);
|
_showChoiceDialog(context);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 50),
|
margin: const EdgeInsets.symmetric(vertical: 50),
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF2BA4EC),
|
color: const Color(0xFF2BA4EC),
|
||||||
borderRadius: BorderRadius.circular(50),
|
borderRadius: BorderRadius.circular(50),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
@@ -451,7 +452,7 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
_showChoiceDialog(context);
|
_showChoiceDialog(context);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 50),
|
margin: const EdgeInsets.symmetric(vertical: 50),
|
||||||
child: ClipOval(
|
child: ClipOval(
|
||||||
child: Image.memory(
|
child: Image.memory(
|
||||||
imageData,
|
imageData,
|
||||||
@@ -469,14 +470,14 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
_showChoiceDialog(context);
|
_showChoiceDialog(context);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 50),
|
margin: const EdgeInsets.symmetric(vertical: 50),
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF2BA4EC),
|
color: const Color(0xFF2BA4EC),
|
||||||
borderRadius: BorderRadius.circular(50),
|
borderRadius: BorderRadius.circular(50),
|
||||||
),
|
),
|
||||||
child: Icon(
|
child: const Icon(
|
||||||
Icons.person,
|
Icons.person,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
size: 90,
|
size: 90,
|
||||||
@@ -492,14 +493,14 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
_showChoiceDialog(context);
|
_showChoiceDialog(context);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 50),
|
margin: const EdgeInsets.symmetric(vertical: 50),
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF2BA4EC),
|
color: const Color(0xFF2BA4EC),
|
||||||
borderRadius: BorderRadius.circular(50),
|
borderRadius: BorderRadius.circular(50),
|
||||||
),
|
),
|
||||||
child: Icon(
|
child: const Icon(
|
||||||
Icons.person,
|
Icons.person,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
size: 90,
|
size: 90,
|
||||||
@@ -547,162 +548,162 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
width: 300,
|
width: 300,
|
||||||
padding: const EdgeInsets.only(top: 0),
|
padding: const EdgeInsets.only(top: 0),
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
TextFormField(
|
TextFormField(
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
controller: _cedulaController,
|
controller: _cedulaController,
|
||||||
validator: (String? value) {
|
validator: (String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Ingrese una cedula válida';
|
return 'Ingrese una cedula válida';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
prefixIcon: Icon(Icons.person_outline),
|
prefixIcon: Icon(Icons.person_outline),
|
||||||
hintText: 'Cedula (Obligatorio)'),
|
hintText: 'Cedula (Obligatorio)'),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
_showChoiceDialogCedula(context);
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFFD6F4FF),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(250, 50),
|
||||||
),
|
),
|
||||||
SizedBox(height: _space),
|
child: Row(
|
||||||
ElevatedButton(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
onPressed: () {
|
children: [
|
||||||
_showChoiceDialogCedula(context);
|
const Text(
|
||||||
},
|
'Cedula',
|
||||||
style: ElevatedButton.styleFrom(
|
style: TextStyle(
|
||||||
backgroundColor: const Color(0xFFD6F4FF),
|
color: Color(0xFF2BA4EC),
|
||||||
shape: RoundedRectangleBorder(
|
fontSize: 17,
|
||||||
borderRadius: BorderRadius.circular(50),
|
),
|
||||||
),
|
),
|
||||||
elevation: 0,
|
const SizedBox(width: 15),
|
||||||
minimumSize: const Size(250, 50),
|
Icon(
|
||||||
),
|
image_cedula != null
|
||||||
child: Row(
|
? Icons.check
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
: Icons.file_upload_outlined,
|
||||||
children: [
|
color: const Color(0xFF2BA4EC),
|
||||||
const Text(
|
size: 30,
|
||||||
'Cedula',
|
),
|
||||||
style: TextStyle(
|
],
|
||||||
color: Color(0xFF2BA4EC),
|
|
||||||
fontSize: 17,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 15),
|
|
||||||
Icon(
|
|
||||||
image_cedula != null
|
|
||||||
? Icons.check
|
|
||||||
: Icons.file_upload_outlined,
|
|
||||||
color: const Color(0xFF2BA4EC),
|
|
||||||
size: 30,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(height: _space),
|
),
|
||||||
TextFormField(
|
SizedBox(height: _space),
|
||||||
readOnly: true,
|
TextFormField(
|
||||||
onTap: () async {
|
readOnly: true,
|
||||||
final String? profesion =
|
onTap: () async {
|
||||||
(await Navigator.pushNamed(
|
final String? profesion = (await Navigator.pushNamed(
|
||||||
context, '/profession')) as String?;
|
context, '/profession')) as String?;
|
||||||
|
|
||||||
if (profesion != null) {
|
if (profesion != null) {
|
||||||
setState(() {
|
|
||||||
_profession = profesion;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
decoration: InputDecoration(
|
|
||||||
prefixIcon:
|
|
||||||
const Icon(Icons.assignment_ind_rounded),
|
|
||||||
suffixIcon: const Icon(Icons.arrow_drop_down),
|
|
||||||
hintStyle: profession == ''
|
|
||||||
? const TextStyle()
|
|
||||||
: const TextStyle(color: Colors.black87),
|
|
||||||
hintText: profession == ''
|
|
||||||
? 'Profesión (Obligatorio)'
|
|
||||||
: profession),
|
|
||||||
),
|
|
||||||
SizedBox(height: _space),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
_showChoiceDialogCertificado(context);
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: const Color(0xFFD6F4FF),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(50),
|
|
||||||
),
|
|
||||||
elevation: 0,
|
|
||||||
minimumSize: const Size(250, 50),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
'Certificado profesional',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xFF2BA4EC),
|
|
||||||
fontSize: 17,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 15),
|
|
||||||
Icon(
|
|
||||||
image_certificado != null
|
|
||||||
? Icons.check
|
|
||||||
: Icons.file_upload_outlined,
|
|
||||||
color: const Color(0xFF2BA4EC),
|
|
||||||
size: 30,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: _space),
|
|
||||||
TextFormField(
|
|
||||||
controller: _especializacionController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
prefixIcon: Icon(Icons.assignment_ind_rounded),
|
|
||||||
hintText: 'Especialización'),
|
|
||||||
),
|
|
||||||
SizedBox(height: _space),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final images = await getImage(3);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
images_especializacion =
|
_profession = profesion;
|
||||||
images.map((e) => File(e!.path)).toList();
|
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
style: ElevatedButton.styleFrom(
|
},
|
||||||
backgroundColor: const Color(0xFFD6F4FF),
|
decoration: InputDecoration(
|
||||||
shape: RoundedRectangleBorder(
|
prefixIcon:
|
||||||
borderRadius: BorderRadius.circular(50),
|
const Icon(Icons.assignment_ind_rounded),
|
||||||
),
|
suffixIcon: const Icon(Icons.arrow_drop_down),
|
||||||
elevation: 0,
|
hintStyle: profession == ''
|
||||||
minimumSize: const Size(250, 50),
|
? const TextStyle()
|
||||||
),
|
: const TextStyle(color: Colors.black87),
|
||||||
child: Row(
|
hintText: profession == ''
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
? 'Profesión (Obligatorio)'
|
||||||
children: [
|
: profession),
|
||||||
const Text(
|
),
|
||||||
'Especialización',
|
SizedBox(height: _space),
|
||||||
style: TextStyle(
|
ElevatedButton(
|
||||||
color: Color(0xFF2BA4EC),
|
onPressed: () {
|
||||||
fontSize: 17,
|
_showChoiceDialogCertificado(context);
|
||||||
),
|
},
|
||||||
),
|
style: ElevatedButton.styleFrom(
|
||||||
const SizedBox(width: 15),
|
backgroundColor: const Color(0xFFD6F4FF),
|
||||||
Icon(
|
shape: RoundedRectangleBorder(
|
||||||
images_especializacion.isEmpty
|
borderRadius: BorderRadius.circular(50),
|
||||||
? Icons.file_upload_outlined
|
|
||||||
: Icons.check,
|
|
||||||
color: const Color(0xFF2BA4EC),
|
|
||||||
size: 30,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(250, 50),
|
||||||
),
|
),
|
||||||
],
|
child: Row(
|
||||||
)),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Certificado profesional',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF2BA4EC),
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Icon(
|
||||||
|
image_certificado != null
|
||||||
|
? Icons.check
|
||||||
|
: Icons.file_upload_outlined,
|
||||||
|
color: const Color(0xFF2BA4EC),
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
TextFormField(
|
||||||
|
controller: _especializacionController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.assignment_ind_rounded),
|
||||||
|
hintText: 'Especialización'),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final images = await getImage(3);
|
||||||
|
setState(() {
|
||||||
|
images_especializacion =
|
||||||
|
images.map((e) => File(e!.path)).toList();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFFD6F4FF),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(250, 50),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Especialización',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF2BA4EC),
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Icon(
|
||||||
|
images_especializacion.isEmpty
|
||||||
|
? Icons.file_upload_outlined
|
||||||
|
: Icons.check,
|
||||||
|
color: const Color(0xFF2BA4EC),
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.only(
|
margin: const EdgeInsets.only(
|
||||||
@@ -721,25 +722,27 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Row(
|
child: const Row(
|
||||||
children: const [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
Icons.error_outline,
|
Icons.error_outline,
|
||||||
size: 27,
|
size: 27,
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
SizedBox(width: 15),
|
SizedBox(width: 15),
|
||||||
Text(
|
Expanded(
|
||||||
'Para añadir mas de una especialidad, \nenvie mas fotos y separe por comas (,).',
|
child: Text(
|
||||||
style: TextStyle(color: Colors.black, fontSize: 14),
|
'Para añadir mas de una especialidad, envie mas fotos y separe por comas (,).',
|
||||||
),
|
style: TextStyle(color: Colors.black, fontSize: 14),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
margin: const EdgeInsets.only(
|
margin: const EdgeInsets.only(
|
||||||
top: 80, right: 70, left: 70, bottom: 30),
|
top: 80, right: 20, left: 20, bottom: 30),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
@@ -753,10 +756,11 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|||||||
),
|
),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
minimumSize: const Size(250, 50),
|
minimumSize: const Size(250, 50),
|
||||||
|
maximumSize: const Size(350, 50),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: const Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: const [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Enviar información',
|
'Enviar información',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|||||||
@@ -0,0 +1,621 @@
|
|||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||||
|
import 'package:prosappco/src/components/photo_view_web.dart';
|
||||||
|
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
class ProfessionalProfileWebScreen extends StatefulWidget {
|
||||||
|
const ProfessionalProfileWebScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ProfessionalProfileWebScreen> createState() =>
|
||||||
|
_ProfessionalProfileWebScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfessionalProfileWebScreenState
|
||||||
|
extends State<ProfessionalProfileWebScreen> {
|
||||||
|
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||||
|
final FirebaseStorage storage = FirebaseStorage.instance;
|
||||||
|
late final FirebaseAuth _auth;
|
||||||
|
|
||||||
|
// variables imagen
|
||||||
|
String selectedImage = '';
|
||||||
|
String selectedCedulaImage = '';
|
||||||
|
String selectedCertificadoImage = '';
|
||||||
|
List selectedEspecializacionImages = [];
|
||||||
|
|
||||||
|
XFile? file;
|
||||||
|
Uint8List? selectedImagInBytes;
|
||||||
|
XFile? image_cedula;
|
||||||
|
Uint8List? imageCedulaBytes;
|
||||||
|
XFile? image_certificado;
|
||||||
|
Uint8List? imageCertificadoBytes;
|
||||||
|
XFile? image_especializaciones;
|
||||||
|
Uint8List? imageespEcializacionesBytes;
|
||||||
|
|
||||||
|
// controllers
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final TextEditingController _cedulaController = TextEditingController();
|
||||||
|
final TextEditingController _especializacionController =
|
||||||
|
TextEditingController();
|
||||||
|
|
||||||
|
// variables
|
||||||
|
bool _isLoading = false;
|
||||||
|
String _profession = '...';
|
||||||
|
String photoTemp = '';
|
||||||
|
String photoCedulaTemp = '';
|
||||||
|
String photoCertificadoTemp = '';
|
||||||
|
String _photo = '...';
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_auth = FirebaseAuth.instance;
|
||||||
|
if (_photo == '...') {
|
||||||
|
AuthenticationRepository.instance.getPhoto(uid.toString()).then(
|
||||||
|
(String s) => setState(() {
|
||||||
|
_photo = s;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_profession == '...') {
|
||||||
|
AuthenticationRepository.instance.getProfession(uid.toString()).then(
|
||||||
|
(String s) => setState(() {
|
||||||
|
_profession = s;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectFile(bool imageFrom) async {
|
||||||
|
FilePickerResult? fileResult = await FilePicker.platform.pickFiles();
|
||||||
|
|
||||||
|
if (fileResult != null) {
|
||||||
|
setState(() {
|
||||||
|
selectedImage = fileResult.files.first.name;
|
||||||
|
selectedImagInBytes = fileResult.files.first.bytes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectFileCedula(bool imageFrom) async {
|
||||||
|
FilePickerResult? fileResult = await FilePicker.platform.pickFiles();
|
||||||
|
|
||||||
|
if (fileResult != null) {
|
||||||
|
setState(() {
|
||||||
|
selectedCedulaImage = fileResult.files.first.name;
|
||||||
|
imageCedulaBytes = fileResult.files.first.bytes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectFileCertificado(bool imageFrom) async {
|
||||||
|
FilePickerResult? fileResult = await FilePicker.platform.pickFiles();
|
||||||
|
|
||||||
|
if (fileResult != null) {
|
||||||
|
setState(() {
|
||||||
|
selectedCertificadoImage = fileResult.files.first.name;
|
||||||
|
imageCertificadoBytes = fileResult.files.first.bytes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectFilesEspecializaciones(bool imageFrom) async {
|
||||||
|
FilePickerResult? fileResult =
|
||||||
|
await FilePicker.platform.pickFiles(allowMultiple: true);
|
||||||
|
|
||||||
|
if (fileResult != null) {
|
||||||
|
setState(() {
|
||||||
|
fileResult.files.forEach((element) {
|
||||||
|
selectedEspecializacionImages.add(element.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
print('array - $selectedEspecializacionImages');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> sendInfo() async {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
final String cedula = _cedulaController.text.trim();
|
||||||
|
|
||||||
|
if (cedula.isEmpty) {
|
||||||
|
showSnackBar('Cedula invalida', 'Ingrese una cedula válida');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageCedulaBytes == null) {
|
||||||
|
showSnackBar('Cedula', 'Ingrese una imagen de su cedula');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageCertificadoBytes == null) {
|
||||||
|
showSnackBar('Certificado', 'Ingrese una imagen de su certificado');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza los datos del usuario en Firestore
|
||||||
|
await FirebaseFirestore.instance.collection('users').doc(uid).update({
|
||||||
|
'cedula': cedula,
|
||||||
|
'estado': 'revision',
|
||||||
|
// 'especializaciones': especializaciones
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sube las imágenes al storage de Firebase
|
||||||
|
await uploadCedula();
|
||||||
|
await uploadCertificado();
|
||||||
|
// uploadEspecializaciones(images_especializacion);
|
||||||
|
|
||||||
|
// Actualiza la imagen de perfil si hay cambios
|
||||||
|
if (selectedImagInBytes != null) {
|
||||||
|
await uploadFile();
|
||||||
|
await updateImage(photoTemp);
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Navega a la siguiente pantalla
|
||||||
|
Navigator.pushReplacementNamed(context, '/solicitudEnviada');
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadFile() async {
|
||||||
|
try {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final formattedDate = DateFormat('HHmmssddMMyyyy').format(now);
|
||||||
|
final milliseconds = (now.microsecondsSinceEpoch / 1000).round();
|
||||||
|
final random = '$formattedDate$milliseconds';
|
||||||
|
|
||||||
|
final Reference ref = FirebaseStorage.instance
|
||||||
|
.ref()
|
||||||
|
.child('users')
|
||||||
|
.child(uid!)
|
||||||
|
.child('profile')
|
||||||
|
.child(random);
|
||||||
|
|
||||||
|
final metaData = SettableMetadata(contentType: 'image/jpeg');
|
||||||
|
|
||||||
|
final UploadTask uploadTask = ref.putData(selectedImagInBytes!, metaData);
|
||||||
|
|
||||||
|
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true);
|
||||||
|
|
||||||
|
photoTemp = ref.fullPath;
|
||||||
|
|
||||||
|
if (snapshot.state == TaskState.success) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('web image error - $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadCedula() async {
|
||||||
|
try {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final formattedDate = DateFormat('HHmmssddMMyyyy').format(now);
|
||||||
|
final milliseconds = (now.microsecondsSinceEpoch / 1000).round();
|
||||||
|
final random = 'c$formattedDate$milliseconds';
|
||||||
|
|
||||||
|
final Reference ref = FirebaseStorage.instance
|
||||||
|
.ref()
|
||||||
|
.child('users')
|
||||||
|
.child(uid!)
|
||||||
|
.child('cedula')
|
||||||
|
.child(random);
|
||||||
|
|
||||||
|
final metaData = SettableMetadata(contentType: 'image/jpeg');
|
||||||
|
|
||||||
|
final UploadTask uploadTask = ref.putData(imageCedulaBytes!, metaData);
|
||||||
|
|
||||||
|
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true);
|
||||||
|
|
||||||
|
photoCedulaTemp = ref.fullPath;
|
||||||
|
|
||||||
|
if (snapshot.state == TaskState.success) {
|
||||||
|
updateImageCedula(photoCedulaTemp);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('web image cedula error - $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadCertificado() async {
|
||||||
|
try {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final formattedDate = DateFormat('HHmmssddMMyyyy').format(now);
|
||||||
|
final milliseconds = (now.microsecondsSinceEpoch / 1000).round();
|
||||||
|
final random = 'f$formattedDate$milliseconds';
|
||||||
|
|
||||||
|
final Reference ref = FirebaseStorage.instance
|
||||||
|
.ref()
|
||||||
|
.child('users')
|
||||||
|
.child(uid!)
|
||||||
|
.child('certificado_profesional')
|
||||||
|
.child(random);
|
||||||
|
|
||||||
|
final metaData = SettableMetadata(contentType: 'image/jpeg');
|
||||||
|
|
||||||
|
final UploadTask uploadTask =
|
||||||
|
ref.putData(imageCertificadoBytes!, metaData);
|
||||||
|
|
||||||
|
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true);
|
||||||
|
|
||||||
|
photoCertificadoTemp = ref.fullPath;
|
||||||
|
|
||||||
|
if (snapshot.state == TaskState.success) {
|
||||||
|
updateImageCertificado(photoCertificadoTemp);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('web image certificado error - $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateImageCedula(image) async {
|
||||||
|
try {
|
||||||
|
final userRef = FirebaseFirestore.instance.collection('users').doc(uid);
|
||||||
|
final userSnapshot = await userRef.get();
|
||||||
|
|
||||||
|
if (userSnapshot.exists) {
|
||||||
|
await userRef.update({'imgCedula': image});
|
||||||
|
print('¡Imagen de cédula actualizada correctamente!');
|
||||||
|
} else {
|
||||||
|
await userRef.set({'imgCedula': image});
|
||||||
|
print('¡Imagen de cédula agregada correctamente!');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error al agregar o actualizar la imagen de cédula: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateImageCertificado(image) async {
|
||||||
|
try {
|
||||||
|
final userRef = FirebaseFirestore.instance.collection('users').doc(uid);
|
||||||
|
final userSnapshot = await userRef.get();
|
||||||
|
|
||||||
|
if (userSnapshot.exists) {
|
||||||
|
await userRef.update({'imgCertificado': image});
|
||||||
|
print('¡Imagen de certificado actualizada correctamente!');
|
||||||
|
} else {
|
||||||
|
await userRef.set({'imgCertificado': image});
|
||||||
|
print('¡Imagen de certificado agregada correctamente!');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error al agregar o actualizar la imagen de certificado: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateImage(image) async {
|
||||||
|
try {
|
||||||
|
await FirebaseFirestore.instance
|
||||||
|
.collection('users')
|
||||||
|
.doc(uid)
|
||||||
|
.update({'photo': image});
|
||||||
|
|
||||||
|
print('imagen actualizada correctamente');
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
await FirebaseFirestore.instance
|
||||||
|
.collection('users')
|
||||||
|
.doc(uid)
|
||||||
|
.set({'photo': image});
|
||||||
|
} catch (e) {
|
||||||
|
print('Error al agregar la imagen de perfil: $e');
|
||||||
|
}
|
||||||
|
|
||||||
|
print('Error al actualizar la imagen de perfil: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showSnackBar(String title, String message) {
|
||||||
|
Get.snackbar(
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
snackPosition: SnackPosition.TOP,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String profession = _profession.toString();
|
||||||
|
double _space = 10;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: PopAppbar(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
label: 'Perfil profesional'),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Center(
|
||||||
|
child: _isLoading
|
||||||
|
? const CircularProgressIndicator()
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: (selectedImagInBytes != null)
|
||||||
|
? LocalPhotoWeb(file: selectedImagInBytes)
|
||||||
|
: ReferencePhotoWeb(ref: storage.ref().child(_photo)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
_selectFile(true);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.image),
|
||||||
|
label: const Text('Elige una imagen'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 300,
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
controller: _cedulaController,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter
|
||||||
|
.digitsOnly // Solo permite caracteres numéricos
|
||||||
|
],
|
||||||
|
validator: (String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Ingrese una cedula válida';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.person_outline),
|
||||||
|
hintText: 'Cedula (Obligatorio)',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
_selectFileCedula(true);
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFFD6F4FF),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(250, 50),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Cedula',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF2BA4EC),
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Icon(
|
||||||
|
imageCedulaBytes != null
|
||||||
|
? Icons.check
|
||||||
|
: Icons.file_upload_outlined,
|
||||||
|
color: const Color(0xFF2BA4EC),
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
TextFormField(
|
||||||
|
readOnly: true,
|
||||||
|
onTap: () async {
|
||||||
|
final String? profesion =
|
||||||
|
(await Navigator.pushNamed(
|
||||||
|
context, '/profession')) as String?;
|
||||||
|
|
||||||
|
if (profesion != null) {
|
||||||
|
setState(() {
|
||||||
|
_profession = profesion;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon:
|
||||||
|
const Icon(Icons.assignment_ind_rounded),
|
||||||
|
suffixIcon: const Icon(Icons.arrow_drop_down),
|
||||||
|
hintStyle: profession == ''
|
||||||
|
? const TextStyle()
|
||||||
|
: const TextStyle(color: Colors.black87),
|
||||||
|
hintText: profession == ''
|
||||||
|
? 'Profesión (Obligatorio)'
|
||||||
|
: profession),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
_selectFileCertificado(true);
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFFD6F4FF),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(250, 50),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Certificado profesional',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF2BA4EC),
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Icon(
|
||||||
|
imageCertificadoBytes != null
|
||||||
|
? Icons.check
|
||||||
|
: Icons.file_upload_outlined,
|
||||||
|
color: const Color(0xFF2BA4EC),
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
TextFormField(
|
||||||
|
controller: _especializacionController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
prefixIcon:
|
||||||
|
Icon(Icons.assignment_ind_rounded),
|
||||||
|
hintText: 'Especialización'),
|
||||||
|
),
|
||||||
|
SizedBox(height: _space),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
_selectFilesEspecializaciones(true);
|
||||||
|
|
||||||
|
// final images = await getImage(3);
|
||||||
|
// setState(() {
|
||||||
|
// images_especializacion =
|
||||||
|
// images.map((e) => File(e!.path)).toList();
|
||||||
|
// });
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFFD6F4FF),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(250, 50),
|
||||||
|
),
|
||||||
|
child: const Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Especialización',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF2BA4EC),
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
// Icon(
|
||||||
|
// images_especializacion.isEmpty
|
||||||
|
// ? Icons.file_upload_outlined
|
||||||
|
// : Icons.check,
|
||||||
|
// color: const Color(0xFF2BA4EC),
|
||||||
|
// size: 30,
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 450,
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
left: 40, right: 40, top: 40, bottom: 0),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20, vertical: 15),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFFD6F4FF),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey.withOpacity(0.5),
|
||||||
|
spreadRadius: 1,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: const Offset(1, 3),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.error_outline,
|
||||||
|
size: 27,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Para añadir mas de una especialidad, envie mas fotos y separe por comas (,).',
|
||||||
|
style:
|
||||||
|
TextStyle(color: Colors.black, fontSize: 14),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
top: 80, right: 20, left: 20, bottom: 30),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
sendInfo();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFF2BA4EC),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(250, 50),
|
||||||
|
maximumSize: const Size(350, 50),
|
||||||
|
),
|
||||||
|
child: const Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Enviar información',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
Icon(
|
||||||
|
Icons.send,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,13 +5,13 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
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/pop_appbar.dart';
|
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||||
import 'package:prosappco/src/controllers/add_name_email_city.dart';
|
import 'package:prosappco/src/controllers/add_name_email_city.dart';
|
||||||
import 'package:prosappco/src/screens/city.dart';
|
import 'package:prosappco/src/screens/city.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/service.dart';
|
|
||||||
import 'package:prosappco/src/services/select_image_profile.dart';
|
import 'package:prosappco/src/services/select_image_profile.dart';
|
||||||
|
|
||||||
import '../components/photo_view.dart';
|
import '../components/photo_view.dart';
|
||||||
@@ -103,14 +103,13 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> uploadImage(File image) async {
|
Future<bool> uploadImage(File image) async {
|
||||||
final String namefile = image.path.split('/').last;
|
final now = DateTime.now();
|
||||||
|
final formattedDate = DateFormat('HHmmssddMMyyyy').format(now);
|
||||||
|
final milliseconds = (now.microsecondsSinceEpoch / 1000).round();
|
||||||
|
final random = '$formattedDate$milliseconds';
|
||||||
|
|
||||||
Reference ref = storage
|
Reference ref =
|
||||||
.ref()
|
storage.ref().child('users').child(uid!).child('profile').child(random);
|
||||||
.child('users')
|
|
||||||
.child(uid!)
|
|
||||||
.child('profile')
|
|
||||||
.child(namefile);
|
|
||||||
|
|
||||||
final UploadTask uploadTask = ref.putFile(image);
|
final UploadTask uploadTask = ref.putFile(image);
|
||||||
|
|
||||||
@@ -231,7 +230,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (newEmail.isEmpty) {
|
if (newEmail.isEmpty) {
|
||||||
// Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario
|
// Si el nuevo email está vacío, no lo actualizamos y mostramos un mensaje al usuario
|
||||||
Get.snackbar(
|
Get.snackbar(
|
||||||
'Correo Invalido',
|
'Correo Invalido',
|
||||||
'Ingrese un email válido.',
|
'Ingrese un email válido.',
|
||||||
@@ -374,12 +373,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 50),
|
margin: const EdgeInsets.symmetric(vertical: 50),
|
||||||
child: (imagen_to_upload != null)
|
child: (imagen_to_upload != null)
|
||||||
? LocalPhoto(
|
? LocalPhoto(file: imagen_to_upload!)
|
||||||
file: imagen_to_upload!,
|
: ReferencePhoto(ref: storage.ref().child(_photo))),
|
||||||
)
|
|
||||||
: ReferencePhoto(
|
|
||||||
ref: storage.ref().child(_photo),
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
width: 300,
|
width: 300,
|
||||||
|
|||||||
@@ -0,0 +1,460 @@
|
|||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:prosappco/src/authentication/authentication_repository.dart';
|
||||||
|
import 'package:prosappco/src/components/photo_view_web.dart';
|
||||||
|
import 'package:prosappco/src/components/pop_appbar.dart';
|
||||||
|
import 'package:prosappco/src/screens/city.dart';
|
||||||
|
import 'package:prosappco/src/screens/new_number.dart';
|
||||||
|
import 'package:prosappco/src/screens/new_password.dart';
|
||||||
|
|
||||||
|
class ProfileWebScreen extends StatefulWidget {
|
||||||
|
const ProfileWebScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ProfileWebScreen> createState() => _ProfileWebScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfileWebScreenState extends State<ProfileWebScreen> {
|
||||||
|
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||||
|
final FirebaseStorage storage = FirebaseStorage.instance;
|
||||||
|
late final FirebaseAuth _auth;
|
||||||
|
|
||||||
|
// variables imagen
|
||||||
|
String selectedImage = '';
|
||||||
|
XFile? file;
|
||||||
|
Uint8List? selectedImagInBytes;
|
||||||
|
String photoTemp = '';
|
||||||
|
|
||||||
|
// controladores
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final TextEditingController _nameController = TextEditingController();
|
||||||
|
final TextEditingController _emailController = TextEditingController();
|
||||||
|
final TextEditingController _phoneNumberController = TextEditingController();
|
||||||
|
final TextEditingController _passwordController = TextEditingController();
|
||||||
|
bool _obscureText = true;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
String _ciudad = '...';
|
||||||
|
String _photo = '...';
|
||||||
|
String? _email = '';
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||||
|
_auth = FirebaseAuth.instance;
|
||||||
|
|
||||||
|
final currentUser = _auth.currentUser;
|
||||||
|
|
||||||
|
if (currentUser != null && currentUser.phoneNumber != null) {
|
||||||
|
_phoneNumberController.text = currentUser.phoneNumber!;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser != null && currentUser.displayName != null) {
|
||||||
|
_nameController.text = currentUser.displayName!;
|
||||||
|
}
|
||||||
|
if (currentUser != null && currentUser.email != null) {
|
||||||
|
_emailController.text = currentUser.email!;
|
||||||
|
}
|
||||||
|
|
||||||
|
_email = currentUser?.email;
|
||||||
|
|
||||||
|
if (_ciudad == '...') {
|
||||||
|
AuthenticationRepository.instance
|
||||||
|
.getCity(uid.toString())
|
||||||
|
.then((String s) => setState(() {
|
||||||
|
_ciudad = s;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_photo == '...') {
|
||||||
|
AuthenticationRepository.instance
|
||||||
|
.getPhoto(uid.toString())
|
||||||
|
.then((String s) => setState(() {
|
||||||
|
_photo = s;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_selectFile(bool imageFrom) async {
|
||||||
|
FilePickerResult? fileResult = await FilePicker.platform.pickFiles();
|
||||||
|
|
||||||
|
if (fileResult != null) {
|
||||||
|
setState(() {
|
||||||
|
selectedImage = fileResult.files.first.name;
|
||||||
|
selectedImagInBytes = fileResult.files.first.bytes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_uploadFile() async {
|
||||||
|
try {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final formattedDate = DateFormat('HHmmssddMMyyyy').format(now);
|
||||||
|
final milliseconds = (now.microsecondsSinceEpoch / 1000).round();
|
||||||
|
final random = '$formattedDate$milliseconds';
|
||||||
|
|
||||||
|
final Reference ref = FirebaseStorage.instance
|
||||||
|
.ref()
|
||||||
|
.child('users')
|
||||||
|
.child(uid!)
|
||||||
|
.child('profile')
|
||||||
|
.child(random);
|
||||||
|
|
||||||
|
final metaData = SettableMetadata(contentType: 'image/jpeg');
|
||||||
|
|
||||||
|
final UploadTask uploadTask = ref.putData(selectedImagInBytes!, metaData);
|
||||||
|
|
||||||
|
final TaskSnapshot snapshot = await uploadTask.whenComplete(() => true);
|
||||||
|
|
||||||
|
photoTemp = ref.fullPath;
|
||||||
|
|
||||||
|
if (snapshot.state == TaskState.success) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('web image error - $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateInfo() async {
|
||||||
|
final currentUser = _auth.currentUser;
|
||||||
|
final currentPhoneNumber = _auth.currentUser!.phoneNumber;
|
||||||
|
|
||||||
|
String newName = _nameController.text.trim();
|
||||||
|
String newEmail = _emailController.text.trim();
|
||||||
|
String newPassword = _passwordController.text.trim();
|
||||||
|
|
||||||
|
if (newName.isEmpty) {
|
||||||
|
// Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario
|
||||||
|
Get.snackbar(
|
||||||
|
'Nombre Invalido',
|
||||||
|
'Ingrese un nombre válido.',
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newEmail.isEmpty) {
|
||||||
|
// Si el nuevo nombre está vacío, no lo actualizamos y mostramos un mensaje al usuario
|
||||||
|
Get.snackbar(
|
||||||
|
'Correo Invalido',
|
||||||
|
'Ingrese un email válido.',
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (currentUser?.displayName != newName) {
|
||||||
|
try {
|
||||||
|
await FirebaseAuth.instance.currentUser!.updateDisplayName(newName);
|
||||||
|
await FirebaseFirestore.instance.collection('users').doc(uid).update({
|
||||||
|
'name': newName,
|
||||||
|
'lowerName': newName.toLowerCase(),
|
||||||
|
});
|
||||||
|
print('Nombre actualizado correctamente');
|
||||||
|
} catch (e) {
|
||||||
|
print('Error al actualizar el nombre: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser?.email != newEmail) {
|
||||||
|
if (newPassword.isNotEmpty) {
|
||||||
|
await FirebaseFirestore.instance.collection('users').doc(uid).update({
|
||||||
|
'email': newEmail,
|
||||||
|
});
|
||||||
|
updateEmailAndPassword(newEmail, newPassword);
|
||||||
|
} else {
|
||||||
|
Get.snackbar(
|
||||||
|
'Contraseña Invalida',
|
||||||
|
'Porfavor ingrese una contraseña.',
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await FirebaseFirestore.instance
|
||||||
|
.collection('users')
|
||||||
|
.doc(uid)
|
||||||
|
.update({'phoneNumber': currentPhoneNumber});
|
||||||
|
} catch (e) {
|
||||||
|
print('e');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (selectedImagInBytes == null) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
await _uploadFile();
|
||||||
|
updateImage(photoTemp);
|
||||||
|
|
||||||
|
//image
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error al actualizar la imagen de perfil $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateImage(image) async {
|
||||||
|
try {
|
||||||
|
await FirebaseFirestore.instance
|
||||||
|
.collection('users')
|
||||||
|
.doc(uid)
|
||||||
|
.update({'photo': image});
|
||||||
|
|
||||||
|
print('imagen actualizada correctamente');
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
await FirebaseFirestore.instance
|
||||||
|
.collection('users')
|
||||||
|
.doc(uid)
|
||||||
|
.set({'photo': image});
|
||||||
|
} catch (e) {
|
||||||
|
print('Error al agregar la imagen de perfil: $e');
|
||||||
|
}
|
||||||
|
|
||||||
|
print('Error al actualizar la imagen de perfil: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateEmailAndPassword(String email, String password) async {
|
||||||
|
final User? user = FirebaseAuth.instance.currentUser;
|
||||||
|
if (user != null) {
|
||||||
|
try {
|
||||||
|
await user.updateEmail(email);
|
||||||
|
await user.updatePassword(password);
|
||||||
|
} catch (e) {
|
||||||
|
Get.snackbar(
|
||||||
|
'Agregar correo',
|
||||||
|
'Inicie sesión para asegurarnos de que seas tú .',
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
);
|
||||||
|
AuthenticationRepository.instance.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String city = _ciudad.toString();
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: PopAppbar(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
label: 'Perfil'),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
reverse: true,
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: (selectedImagInBytes != null)
|
||||||
|
? LocalPhotoWeb(file: selectedImagInBytes)
|
||||||
|
: ReferencePhotoWeb(ref: storage.ref().child(_photo)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
_selectFile(true);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.image),
|
||||||
|
label: const Text('Elige una imagen'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 300,
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
controller: _nameController,
|
||||||
|
maxLength: 50,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Porfavor ingrese un nombre.';
|
||||||
|
}
|
||||||
|
if (value.length < 5) {
|
||||||
|
return 'Debe tener al menos 5 caracteres.';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.person_outline),
|
||||||
|
hintText: 'Nombre (Obligatorio)',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_email != null
|
||||||
|
? TextFormField(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(context, CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return NewPasswordScreen();
|
||||||
|
},
|
||||||
|
));
|
||||||
|
},
|
||||||
|
readOnly: true,
|
||||||
|
controller: _emailController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.email_outlined),
|
||||||
|
hintText: 'Email (Obligatorio)',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: TextFormField(
|
||||||
|
controller: _emailController,
|
||||||
|
validator: (String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Por favor ingrese un email';
|
||||||
|
}
|
||||||
|
final RegExp emailRegExp =
|
||||||
|
RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
|
||||||
|
if (!emailRegExp.hasMatch(value)) {
|
||||||
|
return 'Por favor ingrese un email válido';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.email_outlined),
|
||||||
|
hintText: 'Email (Obligatorio)',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20.0),
|
||||||
|
_email != null
|
||||||
|
? const SizedBox.shrink()
|
||||||
|
: TextFormField(
|
||||||
|
controller: _passwordController,
|
||||||
|
obscureText: _obscureText,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Porfavor ingrese una contraseña.';
|
||||||
|
}
|
||||||
|
if (value.length < 5) {
|
||||||
|
return 'Debe tener al menos 5 caracteres.';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: const Icon(Icons.lock_outline),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
_obscureText
|
||||||
|
? Icons.visibility
|
||||||
|
: Icons.visibility_off,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_obscureText = !_obscureText;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
hintText: 'Contraseña (Obligatorio)',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_email != null
|
||||||
|
? const SizedBox.shrink()
|
||||||
|
: const SizedBox(height: 20.0),
|
||||||
|
TextFormField(
|
||||||
|
readOnly: true,
|
||||||
|
onTap: () async {
|
||||||
|
final String? ciudad = await Navigator.push(
|
||||||
|
context,
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const CityScreen();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
) as String?;
|
||||||
|
|
||||||
|
if (ciudad != null) {
|
||||||
|
setState(() {
|
||||||
|
_ciudad = ciudad;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: const Icon(Icons.near_me),
|
||||||
|
suffixIcon: const Icon(Icons.arrow_drop_down),
|
||||||
|
hintStyle: city == ''
|
||||||
|
? const TextStyle()
|
||||||
|
: const TextStyle(color: Colors.black87),
|
||||||
|
hintText: city == '' ? 'Ciudad' : city,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20.0),
|
||||||
|
TextFormField(
|
||||||
|
controller: _phoneNumberController,
|
||||||
|
readOnly: true,
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const NewNumberScreen();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
prefixIcon: Icon(Icons.phone_android),
|
||||||
|
suffixIcon: Icon(Icons.edit_outlined),
|
||||||
|
hintText: '+57'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
margin: const EdgeInsets.only(top: 50),
|
||||||
|
padding: const EdgeInsets.only(bottom: 30),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
await updateInfo().whenComplete(() {
|
||||||
|
Get.snackbar(
|
||||||
|
'Perfil',
|
||||||
|
'Información actualizada correctamente.',
|
||||||
|
snackPosition: SnackPosition.TOP,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: const Color(0xFF2BA4EC),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
minimumSize: const Size(200, 50),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'Guardar',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -330,8 +330,8 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
|||||||
coordinates = position.target;
|
coordinates = position.target;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
gestureRecognizers: <
|
gestureRecognizers: <Factory<
|
||||||
Factory<OneSequenceGestureRecognizer>>{
|
OneSequenceGestureRecognizer>>{
|
||||||
Factory<OneSequenceGestureRecognizer>(
|
Factory<OneSequenceGestureRecognizer>(
|
||||||
() => EagerGestureRecognizer(),
|
() => EagerGestureRecognizer(),
|
||||||
),
|
),
|
||||||
|
|||||||
+20
-20
@@ -5,10 +5,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _flutterfire_internals
|
name: _flutterfire_internals
|
||||||
sha256: "867b77e2367bc502dcd4d5a66302615409f04eb20ed82ba1c0ba073f9107e018"
|
sha256: "9ebe81588e666f7e2b21309f2b5653bd9642d7f27fd0a6894278d2ff40cb9481"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.2"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -157,50 +157,50 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_auth
|
name: firebase_auth
|
||||||
sha256: "94c229e296a5b9ee5c8cda918e0b320e3a0cc4f6a349cd410c427da347f2a244"
|
sha256: "19508428ca37f611ae47067ee6ebb3ba5a27014941177cc224f71bf7d0720cdd"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.3.0"
|
version: "4.6.2"
|
||||||
firebase_auth_platform_interface:
|
firebase_auth_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_auth_platform_interface
|
name: firebase_auth_platform_interface
|
||||||
sha256: "1217d8aa313b49d58b489aa8879544563abc8793d9612ff20d8df193f202aedc"
|
sha256: e46e136a6f6eec88b30f12445ff7f5b19b23b7ede694921ced4f8eba8eb634f6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.12.0"
|
version: "6.15.2"
|
||||||
firebase_auth_web:
|
firebase_auth_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_auth_web
|
name: firebase_auth_web
|
||||||
sha256: bf7f1a87995a58b0f07dc617806dabd7ff25c64be7fa47b41ab1bb9a485b0062
|
sha256: "553bd576d793d05b920971a2c7ab02bd049d4971153702074ea2555877efd392"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.2.10"
|
version: "5.5.2"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
sha256: dcf54c170c5371ad0e79229d0fb372c58262ae0968b7de222bf28e51dd236be0
|
sha256: e9b36b391690cf329c6fb1de220045e97c13784c303820cd33962319580a56c6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.11.0"
|
version: "2.13.1"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_platform_interface
|
name: firebase_core_platform_interface
|
||||||
sha256: ae79f335f6c7f2dadb00c98c429da2ca905d265e0225fb5e7dfa62ac3accad48
|
sha256: b63e3be6c96ef5c33bdec1aab23c91eb00696f6452f0519401d640938c94cba2
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.7.0"
|
version: "4.8.0"
|
||||||
firebase_core_web:
|
firebase_core_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_web
|
name: firebase_core_web
|
||||||
sha256: e57ef862257a0d977c1308d02e2fbb9b68525e6d85711b08f3df8cec836fb444
|
sha256: "8c0f4c87d20e2d001a5915df238c1f9c88704231f591324205f5a5d2a7740a45"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0"
|
version: "2.5.0"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -229,26 +229,26 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_storage
|
name: firebase_storage
|
||||||
sha256: a27909491c25acef90acc932be4d87bafb9d33fb98678edd2f81eaec9568a109
|
sha256: ba695c4905da360a9daa5ecb12a8c272b2dfd681a12aaf109fa7666abc54f8a5
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.1.0"
|
version: "11.2.2"
|
||||||
firebase_storage_platform_interface:
|
firebase_storage_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_storage_platform_interface
|
name: firebase_storage_platform_interface
|
||||||
sha256: f254e064890df4ee588f10bea06d679e047018910451a4bc3c529b9791adb0a9
|
sha256: "81e8498e26c4ba0a88400666e4f6777ebecf0c49e89d54f9f0f989b249c29abb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.0"
|
version: "4.4.2"
|
||||||
firebase_storage_web:
|
firebase_storage_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_storage_web
|
name: firebase_storage_web
|
||||||
sha256: b6d3c104fecafdce5fe1795306d33856c9a11fa76f73fe7eb062430fc151d686
|
sha256: "4406f263c7a6a53502bde436e0c53ced8385142a2f8ef4005f0781749d87d286"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.0"
|
version: "3.6.2"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|||||||
+4
-4
@@ -37,8 +37,9 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
|
|
||||||
# Google Sign In
|
# Google Sign In
|
||||||
firebase_auth:
|
firebase_auth: ^4.6.2
|
||||||
firebase_core:
|
firebase_core: ^2.13.1
|
||||||
|
file_picker: ^5.3.2
|
||||||
google_sign_in:
|
google_sign_in:
|
||||||
provider:
|
provider:
|
||||||
get:
|
get:
|
||||||
@@ -59,11 +60,10 @@ dependencies:
|
|||||||
community_material_icon: ^5.9.55
|
community_material_icon: ^5.9.55
|
||||||
flutter_email_sender: ^5.2.0
|
flutter_email_sender: ^5.2.0
|
||||||
webview_flutter: ^4.2.0
|
webview_flutter: ^4.2.0
|
||||||
firebase_storage:
|
firebase_storage: ^11.2.2
|
||||||
firebase_messaging: ^14.5.0
|
firebase_messaging: ^14.5.0
|
||||||
flutter_local_notifications: ^14.0.0+1
|
flutter_local_notifications: ^14.0.0+1
|
||||||
responsive_builder: ^0.7.0
|
responsive_builder: ^0.7.0
|
||||||
file_picker: ^5.3.2
|
|
||||||
http: ^0.13.5
|
http: ^0.13.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user