validaciones de inputs
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"projects": {
|
||||
"default": "prosapp-5747a"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"functions": [
|
||||
{
|
||||
"source": "functions",
|
||||
"codebase": "default",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
".git",
|
||||
"firebase-debug.log",
|
||||
"firebase-debug.*.log"
|
||||
],
|
||||
"predeploy": [
|
||||
"npm --prefix \"$RESOURCE_DIR\" run lint",
|
||||
"npm --prefix \"$RESOURCE_DIR\" run build"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings",
|
||||
"plugin:import/typescript",
|
||||
"google",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
project: ["tsconfig.json", "tsconfig.dev.json"],
|
||||
sourceType: "module",
|
||||
},
|
||||
ignorePatterns: [
|
||||
"/lib/**/*", // Ignore built files.
|
||||
],
|
||||
plugins: [
|
||||
"@typescript-eslint",
|
||||
"import",
|
||||
],
|
||||
rules: {
|
||||
"quotes": ["error", "double"],
|
||||
"import/no-unresolved": 0,
|
||||
"indent": ["error", 2],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
# Compiled JavaScript files
|
||||
lib/**/*.js
|
||||
lib/**/*.js.map
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Node.js dependency directory
|
||||
node_modules/
|
||||
Generated
+7882
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "functions",
|
||||
"scripts": {
|
||||
"lint": "eslint --ext .js,.ts .",
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc --watch",
|
||||
"serve": "npm run build && firebase emulators:start --only functions",
|
||||
"shell": "npm run build && firebase functions:shell",
|
||||
"start": "npm run shell",
|
||||
"deploy": "firebase deploy --only functions",
|
||||
"logs": "firebase functions:log"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"firebase-admin": "^11.8.0",
|
||||
"firebase-functions": "^4.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.0",
|
||||
"@typescript-eslint/parser": "^5.12.0",
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"firebase-functions-test": "^3.1.0",
|
||||
"typescript": "^4.9.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import * as functions from "firebase-functions";
|
||||
import * as admin from "firebase-admin";
|
||||
|
||||
admin.initializeApp();
|
||||
const fcm = admin.messaging();
|
||||
|
||||
exports.checkhealth = functions.https.onCall(async (data, context) => {
|
||||
return "The function is online";
|
||||
});
|
||||
|
||||
exports.sendNotification = functions.https.onCall(async (data, context) => {
|
||||
const title = data.title;
|
||||
const body = data.body;
|
||||
const token = data.token;
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
token: token,
|
||||
notification: {
|
||||
title: title,
|
||||
body: body,
|
||||
},
|
||||
data: {
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
|
||||
return fcm.send(payload).then((response) => {
|
||||
return {success: true, response: "Succefully sent message: " + response};
|
||||
}).catch((error) => {
|
||||
return {error: error};
|
||||
});
|
||||
} catch (error) {
|
||||
throw new functions.https.HttpsError("invalid-argument", "error:" + error);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"include": [
|
||||
".eslintrc.js"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"outDir": "lib",
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"target": "es2017"
|
||||
},
|
||||
"compileOnSave": true,
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
@@ -11,8 +11,7 @@ import 'package:prosappco/src/screens/my_services_pro.dart';
|
||||
import 'package:prosappco/src/screens/professional.dart';
|
||||
import 'package:prosappco/src/screens/profile.dart';
|
||||
import 'package:prosappco/src/screens/profile_pro.dart';
|
||||
import 'package:prosappco/src/screens/reputation.dart';
|
||||
|
||||
import 'package:prosappco/src/screens/reputacion_pro.dart';
|
||||
import '../models/scores_model.dart';
|
||||
import '../screens/configuracion.dart';
|
||||
import '../screens/support.dart';
|
||||
@@ -284,7 +283,7 @@ class _DrawerProfessionalState extends State<DrawerProfessional> {
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return ReputationScreen();
|
||||
return ReputationProScreen();
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -18,6 +18,8 @@ class EventoService {
|
||||
double longitude,
|
||||
String status,
|
||||
int? tarifa,
|
||||
bool professionalScored,
|
||||
bool userScored,
|
||||
) async {
|
||||
try {
|
||||
DateTime ahora = DateTime.now();
|
||||
@@ -38,6 +40,8 @@ class EventoService {
|
||||
'status': status,
|
||||
'Timestamp': ahora,
|
||||
'tarifa': tarifa ?? 0,
|
||||
'professional_scored': professionalScored,
|
||||
'user_scored': userScored,
|
||||
}).then((value) {
|
||||
FirebaseFirestore.instance.collection('users').doc(uid).update({
|
||||
'services': FieldValue.arrayUnion([value.id])
|
||||
@@ -138,6 +142,8 @@ class Event {
|
||||
String status;
|
||||
ScoresModel? scoresModel;
|
||||
int? tarifa;
|
||||
bool professionalScored;
|
||||
bool userScored;
|
||||
|
||||
Event({
|
||||
this.id,
|
||||
@@ -154,6 +160,8 @@ class Event {
|
||||
this.latitud,
|
||||
this.status = 'pendiente',
|
||||
this.tarifa,
|
||||
this.professionalScored = false,
|
||||
this.userScored = false,
|
||||
});
|
||||
|
||||
factory Event.fromJson(Map<String, dynamic> json) {
|
||||
@@ -172,6 +180,8 @@ class Event {
|
||||
latitud: json['latitude'] ?? 0,
|
||||
status: json['status'],
|
||||
tarifa: json['tarifa'] ?? 0,
|
||||
professionalScored: json['professional_scored'],
|
||||
userScored: json['user_scored'],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -315,6 +315,8 @@ class _CalendarScreenState extends State<CalendarScreen> {
|
||||
0,
|
||||
'aprobado',
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.then((value) {
|
||||
Navigator.pop(context);
|
||||
|
||||
@@ -124,9 +124,12 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
const SizedBox(width: 12),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
String muestra = _textController.text.trim();
|
||||
if (muestra.isNotEmpty) {
|
||||
final nuevoMensaje = MessageModel(
|
||||
user: uid!,
|
||||
content: _textController.text,
|
||||
content:
|
||||
_textController.text.trimLeft().trimRight(),
|
||||
timestamp: DateTime.now());
|
||||
|
||||
final nuevoMensajeMap = {
|
||||
@@ -143,6 +146,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
});
|
||||
|
||||
_textController.clear();
|
||||
} else {}
|
||||
},
|
||||
child: Container(
|
||||
height: 50,
|
||||
@@ -227,7 +231,9 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
Container(
|
||||
margin: const EdgeInsets.only(left: 60),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10, horizontal: 16),
|
||||
vertical: 10,
|
||||
horizontal: 16,
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFFD5EFFF),
|
||||
borderRadius: BorderRadius.only(
|
||||
|
||||
+109
-16
@@ -34,6 +34,7 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
Reference? ref_photo;
|
||||
ScoresModel? scoresModel;
|
||||
bool? ver = true;
|
||||
bool? pro;
|
||||
|
||||
String formatCurrency(int number) {
|
||||
final formatter =
|
||||
@@ -77,12 +78,14 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
ScoresModel.scoreTo(widget.evento.userId, false, false).then(
|
||||
(ScoresModel s) => setState(() {
|
||||
scoresModel = s;
|
||||
pro = true;
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
ScoresModel.scoreTo(widget.evento.professionalId, true, false).then(
|
||||
(ScoresModel s) => setState(() {
|
||||
scoresModel = s;
|
||||
pro = false;
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -239,14 +242,94 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
style: const TextStyle(
|
||||
color: Colors.grey, fontStyle: FontStyle.italic),
|
||||
),
|
||||
const Padding(
|
||||
widget.evento.status == 'terminado'
|
||||
? const SizedBox(height: 10)
|
||||
: const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 20),
|
||||
child: Text(
|
||||
'Medios de comunicación con el usuario.',
|
||||
style: TextStyle(color: Color(0xFF2BA4EC)),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
widget.evento.status == 'terminado'
|
||||
? pro == true
|
||||
? widget.evento.professionalScored == true
|
||||
? const SizedBox()
|
||||
: Column(
|
||||
children: [
|
||||
const SizedBox(height: 120),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return ScoreScreen(
|
||||
evento: widget.evento,
|
||||
pro: pro!,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2BA4EC),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
elevation: 0,
|
||||
minimumSize: const Size(230, 60),
|
||||
),
|
||||
child: const Text(
|
||||
'Puntuar servicio',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: widget.evento.userScored == true
|
||||
? const SizedBox()
|
||||
: Column(
|
||||
children: [
|
||||
const SizedBox(height: 120),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return ScoreScreen(
|
||||
evento: widget.evento,
|
||||
pro: pro!,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2BA4EC),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
elevation: 0,
|
||||
minimumSize: const Size(230, 60),
|
||||
),
|
||||
child: const Text(
|
||||
'Puntuar servicio',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
const Expanded(child: SizedBox()),
|
||||
ElevatedButton(
|
||||
@@ -263,8 +346,8 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
),
|
||||
),
|
||||
child: const Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(vertical: 18, horizontal: 0),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 18, horizontal: 0),
|
||||
child: Icon(
|
||||
Icons.phone_android,
|
||||
size: 30,
|
||||
@@ -279,18 +362,24 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
await FirebaseFirestore.instance
|
||||
.collection('chats')
|
||||
.doc(widget.evento.id)
|
||||
.set({
|
||||
'professional_id': widget.evento.professionalId,
|
||||
.set(
|
||||
{
|
||||
'professional_id':
|
||||
widget.evento.professionalId,
|
||||
'user_id': widget.evento.userId,
|
||||
'message': [],
|
||||
}, SetOptions(merge: true)).catchError((error) =>
|
||||
print('Error al crear el documento: $error'));
|
||||
},
|
||||
SetOptions(
|
||||
merge:
|
||||
true)).catchError((error) => print(
|
||||
'Error al crear el documento: $error'));
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return ChatScreen(eventoId: widget.evento.id);
|
||||
return ChatScreen(
|
||||
eventoId: widget.evento.id);
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -310,7 +399,8 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
),
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(snackBar);
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@@ -325,8 +415,8 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
),
|
||||
),
|
||||
child: const Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(vertical: 18, horizontal: 0),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 18, horizontal: 0),
|
||||
child: Icon(
|
||||
Icons.message,
|
||||
size: 30,
|
||||
@@ -351,8 +441,8 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
),
|
||||
),
|
||||
child: const Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(vertical: 18, horizontal: 0),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 18, horizontal: 0),
|
||||
child: Icon(
|
||||
CommunityMaterialIcons.whatsapp,
|
||||
size: 30,
|
||||
@@ -563,11 +653,14 @@ class _CitaScreenState extends State<CitaScreen> {
|
||||
.collection("services")
|
||||
.doc('${widget.evento.id}')
|
||||
.update({"status": "terminado"}).then((value) {
|
||||
Navigator.push(
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return ScoreScreen(evento: widget.evento);
|
||||
return ScoreScreen(
|
||||
evento: widget.evento,
|
||||
pro: pro!,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -54,6 +54,16 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
completePhoneNumber = phoneNo.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(
|
||||
|
||||
@@ -146,7 +146,23 @@ class _LoginEmailScreenState extends State<LoginEmailScreen> {
|
||||
padding: const EdgeInsets.only(bottom: 20),
|
||||
child: TextFormField(
|
||||
controller: controller.email,
|
||||
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(
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Color(0xFFECECEC)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Color(0xFFECECEC)),
|
||||
borderRadius: BorderRadius.all(
|
||||
@@ -157,6 +173,12 @@ class _LoginEmailScreenState extends State<LoginEmailScreen> {
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color.fromARGB(255, 184, 0, 0)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
hintText: 'Hello@gmail.com',
|
||||
fillColor: Color.fromARGB(255, 239, 239, 239),
|
||||
filled: true,
|
||||
@@ -177,6 +199,12 @@ class _LoginEmailScreenState extends State<LoginEmailScreen> {
|
||||
child: TextFormField(
|
||||
controller: controller.password,
|
||||
obscureText: _obscureText,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Por favor ingrese una contraseña';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Color(0xFFECECEC)),
|
||||
@@ -188,6 +216,17 @@ class _LoginEmailScreenState extends State<LoginEmailScreen> {
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
border: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Color(0xFFECECEC)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
errorBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color.fromARGB(255, 184, 0, 0)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
hintText: 'Contraseña',
|
||||
fillColor: const Color.fromARGB(255, 239, 239, 239),
|
||||
filled: true,
|
||||
|
||||
@@ -69,6 +69,17 @@ class _NewNumberScreenState extends State<NewNumberScreen> {
|
||||
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(
|
||||
|
||||
@@ -450,7 +450,6 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
String profession = _profession.toString();
|
||||
double _space = 10;
|
||||
|
||||
@@ -493,6 +492,12 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
||||
TextFormField(
|
||||
keyboardType: TextInputType.number,
|
||||
controller: _cedulaController,
|
||||
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)'),
|
||||
@@ -638,13 +643,47 @@ class ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
||||
],
|
||||
)),
|
||||
),
|
||||
Container(
|
||||
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: Row(
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
size: 27,
|
||||
color: Colors.black54,
|
||||
),
|
||||
SizedBox(width: 15),
|
||||
Text(
|
||||
'Para añadir mas de una especialidad, \nenvie mas fotos y separe por comas (,).',
|
||||
style: TextStyle(color: Colors.black, fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.bottomCenter,
|
||||
margin: const EdgeInsets.only(
|
||||
top: 80, right: 70, left: 70, bottom: 30),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
sendInfo();
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2BA4EC),
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:prosappco/src/controllers/add_name_email_city.dart';
|
||||
import 'package:prosappco/src/screens/city.dart';
|
||||
import 'package:prosappco/src/screens/new_number.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 '../components/photo_view.dart';
|
||||
@@ -385,11 +386,21 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
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)'),
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
const SizedBox(height: 0),
|
||||
_email != null
|
||||
? TextFormField(
|
||||
onTap: () {
|
||||
@@ -407,6 +418,17 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
)
|
||||
: 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)'),
|
||||
@@ -490,7 +512,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
await updateInfo();
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2BA4EC),
|
||||
|
||||
@@ -156,7 +156,24 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
||||
padding: const EdgeInsets.only(bottom: 18),
|
||||
child: TextFormField(
|
||||
controller: controller.email,
|
||||
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(
|
||||
border: OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: Color(0xFFECECEC)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: Color(0xFFECECEC)),
|
||||
@@ -169,6 +186,13 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color:
|
||||
Color.fromARGB(255, 184, 0, 0)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
hintText: 'Hello@gmail.com',
|
||||
fillColor: Color.fromARGB(255, 239, 239, 239),
|
||||
filled: true,
|
||||
@@ -189,13 +213,34 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
||||
child: TextFormField(
|
||||
controller: controller.password,
|
||||
obscureText: _obscureText,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Por favor ingrese una contraseña';
|
||||
}
|
||||
if (value.length <= 6) {
|
||||
return 'Contraseña muy corta';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
errorBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color.fromARGB(255, 184, 0, 0)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: Color(0xFFECECEC)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
border: const OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: Color(0xFFECECEC)),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
)),
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: Color(0xFFECECEC)),
|
||||
|
||||
@@ -23,7 +23,7 @@ class _ReputationProScreenState extends State<ReputationProScreen> {
|
||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||
|
||||
if (scoresModel == null) {
|
||||
ScoresModel.scoreFrom(uid.toString(), false, true).then(
|
||||
ScoresModel.scoreTo(uid.toString(), true, true).then(
|
||||
(ScoresModel s) => setState(() => scoresModel = s),
|
||||
);
|
||||
}
|
||||
|
||||
+24
-10
@@ -10,8 +10,8 @@ import 'package:prosappco/src/models/user_model.dart';
|
||||
|
||||
class ScoreScreen extends StatefulWidget {
|
||||
final Event evento;
|
||||
|
||||
const ScoreScreen({super.key, required this.evento});
|
||||
final bool pro;
|
||||
const ScoreScreen({super.key, required this.evento, required this.pro});
|
||||
|
||||
@override
|
||||
State<ScoreScreen> createState() => ScoreScreenState();
|
||||
@@ -46,7 +46,11 @@ class ScoreScreenState extends State<ScoreScreen> {
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: PopAppbar(onPressed: () {}, label: 'Puntuación'),
|
||||
appBar: PopAppbar(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
label: 'Puntuación'),
|
||||
body: Column(
|
||||
children: [
|
||||
Padding(
|
||||
@@ -105,8 +109,8 @@ class ScoreScreenState extends State<ScoreScreen> {
|
||||
),
|
||||
TextFormField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType
|
||||
.multiline, // establece el tipo de teclado como "multilinea"
|
||||
maxLength: 250,
|
||||
keyboardType: TextInputType.multiline,
|
||||
controller: commentController,
|
||||
),
|
||||
],
|
||||
@@ -119,25 +123,35 @@ class ScoreScreenState extends State<ScoreScreen> {
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (widget.evento.professionalId == uid) {
|
||||
if (widget.pro) {
|
||||
FirebaseFirestore.instance
|
||||
.collection("services")
|
||||
.doc(widget.evento.id)
|
||||
.update({'professional_scored': true}).then((value) {
|
||||
FirebaseFirestore.instance.collection("scores").add({
|
||||
"comment": commentController.text,
|
||||
"from_user": uid,
|
||||
"from_user": widget.evento.professionalId,
|
||||
"is_from_professional": false,
|
||||
"score": _rating,
|
||||
"to_user": widget.evento.userId,
|
||||
}).then((value) {
|
||||
// Navigator.pushReplacementNamed(context, '/score');
|
||||
Navigator.pop(context);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
FirebaseFirestore.instance
|
||||
.collection("services")
|
||||
.doc(widget.evento.id)
|
||||
.update({'user_scored': true}).then((value) {
|
||||
FirebaseFirestore.instance.collection("scores").add({
|
||||
"comment": commentController.text,
|
||||
"from_user": uid,
|
||||
"from_user": widget.evento.userId,
|
||||
"is_from_professional": true,
|
||||
"score": _rating,
|
||||
"to_user": widget.evento.professionalId,
|
||||
}).then((value) {
|
||||
// Navigator.pushReplacementNamed(context, '/score');
|
||||
Navigator.pop(context);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:prosappco/src/models/event_model.dart';
|
||||
import 'package:prosappco/src/models/user_model.dart';
|
||||
import 'package:prosappco/src/screens/professional.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:prosappco/src/screens/profile.dart';
|
||||
import 'package:prosappco/src/screens/service_after.dart';
|
||||
import 'package:prosappco/src/screens/service_type.dart';
|
||||
|
||||
@@ -108,6 +109,7 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
final TimeOfDay? pickedTime = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.now(),
|
||||
|
||||
// builder: (context, child) {
|
||||
// return Theme(data: ThemeData.dark(), child: child!);
|
||||
// },
|
||||
@@ -131,6 +133,7 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
|
||||
final FirebaseStorage storage = FirebaseStorage.instance;
|
||||
final uid = AuthenticationRepository.instance.getCurrentUserUid();
|
||||
UserModel? user;
|
||||
final fcmToken = FirebaseMessaging.instance.getToken();
|
||||
|
||||
BitmapDescriptor? _markerIcon;
|
||||
@@ -150,6 +153,12 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
}
|
||||
});
|
||||
|
||||
if (user == null) {
|
||||
UserModel.getUser(uid.toString()).then(
|
||||
(UserModel s) => setState(() => user = s),
|
||||
);
|
||||
}
|
||||
|
||||
BitmapDescriptor.fromAssetImage(
|
||||
const ImageConfiguration(size: Size(48, 48)),
|
||||
'images/pro_marke.png')
|
||||
@@ -566,6 +575,20 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
const SizedBox(height: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (user?.name == null ||
|
||||
user?.name == '' ||
|
||||
user?.phoneNumber == null ||
|
||||
user?.phoneNumber == '') {
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const ProfileScreen();
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
try {
|
||||
final DateTime combinedDate = DateTime(
|
||||
_selectedDate!.year,
|
||||
_selectedDate!.month,
|
||||
@@ -573,10 +596,11 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
_selectedTime!.hour,
|
||||
_selectedTime!.minute);
|
||||
|
||||
DateTime time2 =
|
||||
combinedDate.add(const Duration(hours: 2));
|
||||
DateTime time2 = combinedDate
|
||||
.add(const Duration(hours: 2));
|
||||
|
||||
UserModel.getUser(uid.toString()).then((value) {
|
||||
UserModel.getUser(uid.toString())
|
||||
.then((value) {
|
||||
eventoService
|
||||
.createEvent(
|
||||
value.name,
|
||||
@@ -597,6 +621,8 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
professionalTarifa == 0
|
||||
? 0
|
||||
: professionalTarifa,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.then((value) {
|
||||
Navigator.pushReplacement(
|
||||
@@ -611,6 +637,14 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
);
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
'Llena todos los campos',
|
||||
'Asegurate de llenar todos los campos.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2BA4EC),
|
||||
@@ -629,7 +663,7 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Text('${_selectedDate?.weekday}')
|
||||
Text('${_selectedDate?.weekday}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user