408 lines
18 KiB
Dart
408 lines
18 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
|
import 'package:injector/injector.dart';
|
|
import 'package:prosappco/blocs/score_bloc/score_bloc.dart';
|
|
import 'package:prosappco/blocs/service_bloc/service_bloc.dart';
|
|
import 'package:prosappco/components/general_reputation.dart';
|
|
import 'package:score_repository/score_repository.dart';
|
|
import 'package:service_repository/service_repository.dart';
|
|
import 'package:user_repository/user_repository.dart';
|
|
|
|
class ScoreScreen extends StatefulWidget {
|
|
final ServiceEntity service;
|
|
|
|
const ScoreScreen({Key? key, required this.service}) : super(key: key);
|
|
|
|
@override
|
|
State<ScoreScreen> createState() => _ScoreScreenState();
|
|
}
|
|
|
|
class _ScoreScreenState extends State<ScoreScreen> {
|
|
double _rating = 1.0;
|
|
TextEditingController commentController = TextEditingController();
|
|
late Future<List<dynamic>> _userInfoFuture;
|
|
late bool isProfessional;
|
|
late String userId;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_userInfoFuture = _getUserAndProfessionalInfo(widget.service);
|
|
isProfessional =
|
|
FirebaseAuth.instance.currentUser!.uid == widget.service.userId
|
|
? true
|
|
: false;
|
|
|
|
userId =
|
|
isProfessional ? widget.service.professionalId : widget.service.userId;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocProvider(
|
|
create: (context) => Injector.appInstance.get<ScoreBloc>(),
|
|
child: Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Calificación'),
|
|
),
|
|
body: Column(
|
|
children: [
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
FutureBuilder(
|
|
future: _userInfoFuture,
|
|
builder:
|
|
(context, AsyncSnapshot<List<dynamic>> snapshot) {
|
|
if (snapshot.connectionState ==
|
|
ConnectionState.waiting) {
|
|
return const Center(
|
|
child: CircularProgressIndicator());
|
|
} else {
|
|
if (snapshot.hasError) {
|
|
return Center(
|
|
child:
|
|
Text('Error inesperado: ${snapshot.error}'),
|
|
);
|
|
} else {
|
|
final userInfo = snapshot.data![0] as MyUser;
|
|
|
|
return SizedBox(
|
|
width: double.infinity,
|
|
child: Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Container(
|
|
width: 95,
|
|
height: 95,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
image: userInfo.picture == null
|
|
? null
|
|
: DecorationImage(
|
|
image: NetworkImage(
|
|
userInfo.picture!),
|
|
fit: BoxFit.contain,
|
|
),
|
|
),
|
|
child: userInfo.picture == null
|
|
? Icon(
|
|
CupertinoIcons.person,
|
|
color: Colors.grey.shade400,
|
|
size: 50,
|
|
)
|
|
: null,
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
'${userInfo.name}',
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 15,
|
|
)
|
|
],
|
|
),
|
|
GeneralReputation(
|
|
userId: userId,
|
|
builder: (BuildContext context,
|
|
ReputationEntity reputation) {
|
|
final double average;
|
|
|
|
if (isProfessional) {
|
|
average = reputation.averagePro;
|
|
} else {
|
|
average = reputation.average;
|
|
}
|
|
|
|
return Positioned(
|
|
top: 3,
|
|
right:
|
|
MediaQuery.of(context).size.width *
|
|
0.3,
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 10,
|
|
vertical: 3,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius:
|
|
BorderRadius.circular(20),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black
|
|
.withOpacity(0.1),
|
|
spreadRadius: 1,
|
|
blurRadius: 2,
|
|
offset: const Offset(
|
|
0,
|
|
1,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Icon(
|
|
Icons.star,
|
|
color: Colors.yellow,
|
|
size: 20,
|
|
),
|
|
const SizedBox(width: 4),
|
|
Flexible(
|
|
child: Text(
|
|
average.toStringAsFixed(2),
|
|
style: const TextStyle(
|
|
fontSize: 15,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
);
|
|
// Padding(
|
|
// padding: const EdgeInsets.symmetric(horizontal: 15),
|
|
// child: ListTile(
|
|
// leading: Container(
|
|
// width: 60,
|
|
// height: 60,
|
|
// decoration: BoxDecoration(
|
|
// color: Colors.grey.shade300,
|
|
// shape: BoxShape.circle,
|
|
// image: userInfo.picture == null
|
|
// ? null
|
|
// : DecorationImage(
|
|
// image: NetworkImage(
|
|
// userInfo.picture ?? ''),
|
|
// fit: BoxFit.contain,
|
|
// ),
|
|
// ),
|
|
// child: userInfo.picture == null
|
|
// ? Icon(
|
|
// CupertinoIcons.person,
|
|
// color: Colors.grey.shade400,
|
|
// size: 40,
|
|
// )
|
|
// : null,
|
|
// ),
|
|
// title: Text(
|
|
// userInfo.name ?? '',
|
|
// overflow: TextOverflow.ellipsis,
|
|
// style: const TextStyle(
|
|
// fontSize: 15,
|
|
// fontWeight: FontWeight.w600,
|
|
// ),
|
|
// ),
|
|
// subtitle: const Text(
|
|
// 'Rating: 5.0',
|
|
// style: TextStyle(
|
|
// fontSize: 13,
|
|
// color: Colors.blue,
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// );
|
|
}
|
|
}
|
|
},
|
|
),
|
|
const SizedBox(height: 10),
|
|
const Text(
|
|
'Califica el servicio',
|
|
style:
|
|
TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
|
|
),
|
|
const SizedBox(height: 10),
|
|
RatingBar.builder(
|
|
initialRating: _rating,
|
|
minRating: 1,
|
|
direction: Axis.horizontal,
|
|
allowHalfRating: true,
|
|
itemCount: 5,
|
|
itemSize: 40,
|
|
glow: false,
|
|
maxRating: 5,
|
|
itemPadding: const EdgeInsets.symmetric(horizontal: 5),
|
|
itemBuilder: (context, _) => const Icon(
|
|
Icons.star,
|
|
color: Color(0xFF2BA4EC),
|
|
),
|
|
onRatingUpdate: (rating) {
|
|
setState(() {
|
|
_rating = rating;
|
|
});
|
|
},
|
|
ignoreGestures: false,
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 8),
|
|
child: Text(
|
|
customMessage(_rating),
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
color: Color(0xFF2BA4EC),
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 40, vertical: 40),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'Comentario',
|
|
style: TextStyle(
|
|
fontSize: 20, fontWeight: FontWeight.w600),
|
|
),
|
|
TextFormField(
|
|
maxLines: null,
|
|
maxLength: 400,
|
|
keyboardType: TextInputType.multiline,
|
|
controller: commentController,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
const Divider(
|
|
height: 1,
|
|
thickness: 0.5,
|
|
),
|
|
BlocProvider<ServiceBloc>(
|
|
create: (context) => Injector.appInstance.get<ServiceBloc>(),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 10,
|
|
horizontal: 15,
|
|
),
|
|
child: BlocBuilder<ServiceBloc, ServiceState>(
|
|
builder: (context, serviceState) {
|
|
return FilledButton(
|
|
onPressed: () {
|
|
final CommentEntity comment = widget.service.userId ==
|
|
FirebaseAuth.instance.currentUser!.uid
|
|
? CommentEntity(
|
|
serviceId: widget.service.id!,
|
|
authorId:
|
|
FirebaseAuth.instance.currentUser!.uid,
|
|
isFromUser: true,
|
|
score: _rating,
|
|
destinationId: widget.service.professionalId,
|
|
content: commentController.text.trim(),
|
|
createdAt: Timestamp.now(),
|
|
)
|
|
: CommentEntity(
|
|
serviceId: widget.service.id!,
|
|
authorId:
|
|
FirebaseAuth.instance.currentUser!.uid,
|
|
isFromUser: false,
|
|
score: _rating,
|
|
destinationId: widget.service.userId,
|
|
content: commentController.text.trim(),
|
|
createdAt: Timestamp.now(),
|
|
);
|
|
|
|
BlocProvider.of<ScoreBloc>(context)
|
|
.add(SendScoreEvent(comment: comment));
|
|
|
|
if (widget.service.userId ==
|
|
FirebaseAuth.instance.currentUser!.uid) {
|
|
context.read<ServiceBloc>().add(
|
|
UpdateProfessionalScored(widget.service.id!));
|
|
} else {
|
|
context
|
|
.read<ServiceBloc>()
|
|
.add(UpdateUserScored(widget.service.id!));
|
|
}
|
|
|
|
Navigator.pop(context);
|
|
},
|
|
style: FilledButton.styleFrom(
|
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
|
padding: const EdgeInsets.symmetric(vertical: 15),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
),
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
width: double.infinity,
|
|
child: const Text(
|
|
'Enviar calificación',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 18,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
String customMessage(double rating) {
|
|
if (rating > 4.0) {
|
|
return '¡Excelente! 👏🌟';
|
|
}
|
|
|
|
if (rating < 2.0) {
|
|
return '¡Malo! 😔❌';
|
|
}
|
|
|
|
if (rating <= 4.0 && rating >= 3.0) {
|
|
return '¡Bueno! 👍😊';
|
|
}
|
|
|
|
if (rating < 3.0 && rating >= 2.0) {
|
|
return '¡Regular! 😐🔄';
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
Future<List<dynamic>> _getUserAndProfessionalInfo(
|
|
ServiceEntity service) async {
|
|
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
|
|
|
final MyUser? userInfo;
|
|
|
|
if (FirebaseAuth.instance.currentUser!.uid == service.userId) {
|
|
userInfo = await userRepo.getMyUser(service.professionalId);
|
|
} else {
|
|
userInfo = await userRepo.getMyUser(service.userId);
|
|
}
|
|
|
|
return [userInfo];
|
|
}
|
|
}
|