update
This commit is contained in:
@@ -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, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)),
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user