This commit is contained in:
Juan Felipe Duarte
2023-04-17 11:29:27 -05:00
parent a22d17b199
commit 672e7fc32f
6 changed files with 194 additions and 88 deletions
+47
View File
@@ -0,0 +1,47 @@
class ScoreModel {
final int total;
final double average;
final List<ScoreDetailsModel> details;
ScoreModel(this.total, this.average, this.details);
factory ScoreModel.fromJson(Map<String, dynamic>? json) {
try {
if (json == null) return ScoreModel(0, 0, []);
return ScoreModel(
json['total'],
json['promedio'],
(json['detalles'] as List<dynamic>?)
?.map((e) => ScoreDetailsModel.fromJson(e))
.toList() ??
[],
);
} catch (e) {
print('XD 54 $e');
return ScoreModel(0, 0, []);
}
}
}
class ScoreDetailsModel {
final String userId;
final double score;
final String comment;
ScoreDetailsModel(this.userId, this.score, this.comment);
factory ScoreDetailsModel.fromJson(Map<String, dynamic>? json) {
try {
if (json == null) return ScoreDetailsModel("no user", 0, "");
return ScoreDetailsModel(
json['usuario_id'],
(json['puntaje'] is int) ? json['puntaje'].toDouble() : json['puntaje'],
json['comentario'],
);
} catch (e) {
print('XD $e');
return ScoreDetailsModel("no user", 0, "");
}
}
}
+4
View File
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/photo_view.dart'; import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/score_model.dart';
import 'package:prosappco/src/screens/professional_info.dart'; import 'package:prosappco/src/screens/professional_info.dart';
class ProfessionalScreen extends StatefulWidget { class ProfessionalScreen extends StatefulWidget {
@@ -28,6 +29,7 @@ class Professional {
final String cityName; final String cityName;
final String ubicacion; final String ubicacion;
final List<String> professionalEspecializado; final List<String> professionalEspecializado;
final ScoreModel puntuacion;
Professional({ Professional({
required this.professionalRef, required this.professionalRef,
@@ -36,6 +38,7 @@ class Professional {
required this.cityName, required this.cityName,
required this.ubicacion, required this.ubicacion,
required this.professionalEspecializado, required this.professionalEspecializado,
required this.puntuacion,
}); });
String getEspecializaciones() { String getEspecializaciones() {
@@ -81,6 +84,7 @@ Future<List<Professional>> getProfessionals() async {
professionalRef: storage.ref().child(_photo), professionalRef: storage.ref().child(_photo),
professionalEspecializado: especializaciones, professionalEspecializado: especializaciones,
ubicacion: data['ubicacion'], ubicacion: data['ubicacion'],
puntuacion: ScoreModel.fromJson(data['puntuacion']),
); );
professionals.add(professional); professionals.add(professional);
} }
+128 -81
View File
@@ -1,13 +1,50 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/photo_view.dart'; import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
import 'package:prosappco/src/models/score_model.dart';
import 'package:prosappco/src/screens/professional.dart'; import 'package:prosappco/src/screens/professional.dart';
class ProfessionalInfoScreen extends StatelessWidget { class ProfessionalInfoScreen extends StatefulWidget {
Professional professional; Professional professional;
ProfessionalInfoScreen({super.key, required this.professional}); ProfessionalInfoScreen({super.key, required this.professional});
@override
State<ProfessionalInfoScreen> createState() => _ProfessionalInfoScreenState();
}
class _ProfessionalInfoScreenState extends State<ProfessionalInfoScreen> {
late final FirebaseAuth _auth;
final FirebaseStorage storage = FirebaseStorage.instance;
final uid = AuthenticationRepository.instance.getCurrentUserUid();
@override
void initState() {
super.initState();
_auth = FirebaseAuth.instance;
}
List<String> months = [
'enero',
'febrero',
'marzo',
'abril',
'mayo',
'junio',
'julio',
'agosto',
'septiembre',
'octubre',
'noviembre',
'diciembre',
];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SafeArea( return SafeArea(
@@ -16,7 +53,7 @@ class ProfessionalInfoScreen extends StatelessWidget {
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
}, },
label: professional.name), label: widget.professional.name),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Stack( child: Stack(
children: [ children: [
@@ -46,26 +83,26 @@ class ProfessionalInfoScreen extends StatelessWidget {
height: 5, height: 5,
), ),
Text( Text(
professional.name, widget.professional.name,
style: const TextStyle(fontWeight: FontWeight.w500), style: const TextStyle(fontWeight: FontWeight.w500),
), ),
Text( Text(
professional.professionName, widget.professional.professionName,
style: const TextStyle(color: Color(0xFF1688C9)), style: const TextStyle(color: Color(0xFF1688C9)),
), ),
professional.getEspecializaciones().isEmpty widget.professional.getEspecializaciones().isEmpty
? const SizedBox() ? const SizedBox()
: Text( : Text(
'Especializado/a en ${professional.getEspecializaciones()}', 'Especializado/a en ${widget.professional.getEspecializaciones()}',
style: const TextStyle(color: Colors.black54), style: const TextStyle(color: Colors.black54),
), ),
Text( Text(
professional.cityName, widget.professional.cityName,
), ),
], ],
), ),
), ),
professional.ubicacion == 'domicilio' widget.professional.ubicacion == 'domicilio'
? Container( ? Container(
margin: const EdgeInsets.only( margin: const EdgeInsets.only(
left: 40, right: 40, top: 20, bottom: 20), left: 40, right: 40, top: 20, bottom: 20),
@@ -127,82 +164,33 @@ class ProfessionalInfoScreen extends StatelessWidget {
style: TextStyle(color: Colors.black), style: TextStyle(color: Colors.black),
), ),
subtitle: Row( subtitle: Row(
children: const [ children: [
Icon(Icons.star), RatingBar.builder(
Icon(Icons.star), initialRating:
Icon(Icons.star), widget.professional.puntuacion.average,
Icon(Icons.star), minRating: 1,
Icon(Icons.star_half), direction: Axis.horizontal,
allowHalfRating: true,
itemCount: 5,
itemSize: 25,
maxRating: 5,
itemPadding:
const EdgeInsets.symmetric(horizontal: 0),
itemBuilder: (context, _) => const Icon(
Icons.star,
color: Color(0xFF2BA4EC),
),
onRatingUpdate: (rating) {},
ignoreGestures: true,
),
const SizedBox(width: 5),
Text(
'(${widget.professional.puntuacion.total.toString()}) ${widget.professional.puntuacion.average.toString()}'),
], ],
), ),
), ),
), ),
ListTile( ..._scoresList(widget.professional.puntuacion.details),
onTap: () {},
leading: ReferencePhoto(
ref: professional.professionalRef,
size: 50,
sizeCircle: 50,
sizeIcon: 35,
),
title: Row(
children: const [
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star_half),
],
),
subtitle: const Text(
'Mi perfil',
style: TextStyle(fontSize: 15),
),
),
ListTile(
onTap: () {},
leading: ReferencePhoto(
ref: professional.professionalRef,
size: 50,
sizeCircle: 50,
sizeIcon: 35,
),
title: Row(
children: const [
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
],
),
subtitle: const Text(
'Mi perfil',
style: TextStyle(fontSize: 15),
),
),
ListTile(
onTap: () {},
leading: ReferencePhoto(
ref: professional.professionalRef,
sizeCircle: 50,
sizeIcon: 35,
size: 50,
),
title: Row(
children: const [
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star_border),
],
),
subtitle: const Text(
'Mi perfil',
style: TextStyle(fontSize: 15),
),
),
const SizedBox( const SizedBox(
height: 10, height: 10,
), ),
@@ -214,7 +202,7 @@ class ProfessionalInfoScreen extends StatelessWidget {
left: 10, left: 10,
), ),
child: ReferencePhoto( child: ReferencePhoto(
ref: professional.professionalRef, ref: widget.professional.professionalRef,
size: 100, size: 100,
sizeCircle: 100, sizeCircle: 100,
sizeIcon: 50, sizeIcon: 50,
@@ -226,4 +214,63 @@ class ProfessionalInfoScreen extends StatelessWidget {
), ),
); );
} }
List<Widget> _scoresList(List<ScoreDetailsModel> list) {
return list.map((e) => _scoreItem(e)).toList();
}
Widget _scoreItem(ScoreDetailsModel scoreDetails) {
return ListTile(
onTap: () {},
leading: ReferencePhoto(
ref: widget.professional.professionalRef,
size: 50,
sizeCircle: 50,
sizeIcon: 35,
),
title: Row(
children: [
RatingBar.builder(
initialRating: scoreDetails.score,
minRating: 1,
direction: Axis.horizontal,
allowHalfRating: true,
itemCount: 5,
itemSize: 22,
maxRating: 5,
itemPadding: const EdgeInsets.symmetric(horizontal: 0),
itemBuilder: (context, _) => const Icon(
Icons.star,
color: Color(0xFF2BA4EC),
),
onRatingUpdate: (rating) {},
ignoreGestures: true,
),
Text(
' (${scoreDetails.score})',
style: const TextStyle(color: Colors.black54, fontSize: 13),
)
],
),
subtitle: Row(
children: [
Expanded(
child: Text.rich(
TextSpan(
children: [
const TextSpan(
text: 'name, ',
style: TextStyle(fontSize: 15, color: Colors.black),
),
TextSpan(
text: '"${scoreDetails.comment}"',
style: const TextStyle(fontSize: 15, color: Colors.grey),
),
],
),
),
),
],
));
}
} }
+6 -7
View File
@@ -5,7 +5,6 @@ import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get/get_connect/http/src/utils/utils.dart';
import 'package:prosappco/src/authentication/authentication_repository.dart'; import 'package:prosappco/src/authentication/authentication_repository.dart';
import 'package:prosappco/src/components/photo_view.dart'; import 'package:prosappco/src/components/photo_view.dart';
import 'package:prosappco/src/components/pop_appbar.dart'; import 'package:prosappco/src/components/pop_appbar.dart';
@@ -69,7 +68,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)),
@@ -82,9 +81,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)),
@@ -114,7 +113,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)),
@@ -127,9 +126,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)),
+8
View File
@@ -214,6 +214,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.9" version: "2.0.9"
flutter_rating_bar:
dependency: "direct main"
description:
name: flutter_rating_bar
sha256: d2af03469eac832c591a1eba47c91ecc871fe5708e69967073c043b2d775ed93
url: "https://pub.dev"
source: hosted
version: "4.0.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
+1
View File
@@ -50,6 +50,7 @@ dependencies:
firebase_storage: ^11.1.0 firebase_storage: ^11.1.0
image_picker: ^0.8.7+1 image_picker: ^0.8.7+1
flutter_animate: ^4.1.1+1 flutter_animate: ^4.1.1+1
flutter_rating_bar: ^4.0.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: