Created
January 24, 2022 19:32
-
-
Save guilhermecarvalhocarneiro/c35339ee954a068ff02a9d2408af2d54 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/cupertino.dart'; | |
/// [Travar o arquivo] | |
/// Caso deseje \"travar\" o arquivo para não ser parseado novamente | |
/// pelo manage do Django adicione um # antes da palavra abaixo | |
/// #FileLocked | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/rendering.dart'; | |
import 'package:flutter/scheduler.dart'; | |
import 'package:flutter_bloc/flutter_bloc.dart'; | |
import 'package:google_maps_flutter/google_maps_flutter.dart'; | |
import 'package:help/apps/atendimento/agendamento/model.dart'; | |
import 'package:help/apps/usuario/profissional/cubit.dart'; | |
import 'package:help/apps/usuario/profissional/model.dart'; | |
import 'package:help/user_interface/font.dart'; | |
import 'package:help/utils/config.dart'; | |
import 'package:help/utils/util.dart'; | |
import 'package:location/location.dart'; | |
import 'package:cached_network_image/cached_network_image.dart'; | |
import '../../../../user_interface/widget.dart'; | |
class GeneralProfessionalPage extends StatefulWidget { | |
@override | |
_GeneralProfessionalPageState createState() => _GeneralProfessionalPageState(); | |
} | |
class _GeneralProfessionalPageState extends State<GeneralProfessionalPage> with SingleTickerProviderStateMixin { | |
final _scaffoldKey = GlobalKey<ScaffoldState>(); | |
AnimationController _animationController; | |
final _formGeneralProfessional = GlobalKey<FormState>(); | |
ScrollController _scrollController = ScrollController(); | |
ProfessionalModel _professionalModel; | |
@override | |
void initState() { | |
super.initState(); | |
_animationController = AnimationController(vsync: this); | |
SchedulerBinding.instance.addPostFrameCallback((timeStamp) { | |
_loadData(); | |
}); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return SafeArea( | |
child: Scaffold( | |
key: _scaffoldKey, | |
backgroundColor: customYellowButtonConfirm, | |
body: Container( | |
height: Util.getUtilAreaScreenHeight(context), | |
color: customBodyBackgroundColor, | |
margin: const EdgeInsets.only(top: heightAppBarPage), | |
child: _buildBody(), | |
), | |
), | |
); | |
} | |
Widget _buildBody() { | |
return RefreshIndicator( | |
onRefresh: _refreshData, | |
child: SingleChildScrollView( | |
physics: AlwaysScrollableScrollPhysics(), | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
mainAxisSize: MainAxisSize.max, | |
children: [ | |
customAppBarWithLogo(context, navigationBack: false), | |
Container( | |
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), | |
child: customTitlePage(context, "Solicitações de Serviços"), | |
), | |
BlocConsumer<ProfessionalCubit, ProfessionalState>( | |
listener: (context, state) { | |
if (state is ProfessionalErrorState) { | |
_showMessage(state.error, error: true); | |
} | |
if (state is ProfessionalSuccessState) { | |
_showMessage(state.successMessage); | |
} | |
}, | |
builder: (context, state) { | |
if (state is ProfessionalProcessState) { | |
return customLayoutBuilderProcessingCardModal(context); | |
} | |
if (state is ProfessionalSuccessState) { | |
if (state.professionalDemandList == null) { | |
return Container( | |
child: Center( | |
child: customEmptyData(message: "Nenhuma solicitação de serviço encontrada."), | |
), | |
); | |
} | |
if (state.professionalDemandList.length == 0) { | |
return Container( | |
child: Center( | |
child: customEmptyData(message: "Nenhuma solicitação de serviço encontrada."), | |
), | |
); | |
} | |
return Container( | |
margin: const EdgeInsets.symmetric( | |
vertical: 12, | |
horizontal: 8, | |
), | |
child: ListView.builder( | |
controller: _scrollController, | |
itemCount: state.professionalDemandList.length, | |
itemBuilder: (BuildContext context, int index) { | |
final demand = state.professionalDemandList[index]; | |
return _buildCardDemand(demand); | |
}, | |
shrinkWrap: true, | |
physics: ScrollPhysics(), | |
), | |
); | |
} | |
return Container(); | |
}, | |
), | |
], | |
), | |
), | |
); | |
} | |
Widget _buildCardDemand(ScheduleModel demand) { | |
String destinationAddress = ""; | |
if (demand.enderecoAtendimento != null) { | |
destinationAddress = demand.enderecoAtendimento; | |
} | |
if (destinationAddress.isEmpty) { | |
destinationAddress = demand.fkCliente.enderecoRes; | |
} | |
return Card( | |
child: Container( | |
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8.0), | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
mainAxisAlignment: MainAxisAlignment.center, | |
mainAxisSize: MainAxisSize.max, | |
children: [ | |
Row( | |
children: [ | |
_buildClientePictureDemand(context, demand), | |
_buildClientDataDemand(demand, destinationAddress), | |
], | |
), | |
Padding( | |
padding: const EdgeInsets.symmetric(vertical: 14), | |
child: Center( | |
child: Text( | |
demand.getDemandDate, | |
style: TextStyle( | |
color: customBlueDark, | |
fontWeight: FontWeight.bold, | |
fontSize: 22, | |
), | |
), | |
), | |
), | |
_buildDescriptionServiceArea(demand), | |
SizedBox(height: 22), | |
_buildDemandDataFilterArea(demand), | |
SizedBox(height: 22), | |
_buildDemandTicket(demand), | |
SizedBox(height: 12), | |
_buildRejectButton(demand), | |
], | |
), | |
), | |
); | |
} | |
/// Método para criar a imagem do cliente da demanda | |
Widget _buildClientePictureDemand(BuildContext context, ScheduleModel demand) { | |
return Padding( | |
padding: const EdgeInsets.only(right: 10.0), | |
child: demand.fkCliente.clientHasPicture ? _buildProfileImage(demand.fkCliente.foto) : _buildProfileImageAsset(), | |
); | |
} | |
/// Método para criar a estrutura dos dados do cliente da demanda | |
Widget _buildClientDataDemand(ScheduleModel demand, String destinationAddress) { | |
return Flexible( | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
mainAxisSize: MainAxisSize.max, | |
children: [ | |
Text( | |
demand.fkCliente.nome, | |
style: TextStyle( | |
color: customBlueDark, | |
fontWeight: FontWeight.bold, | |
fontSize: 22, | |
), | |
), | |
Row( | |
children: [ | |
Container( | |
width: MediaQuery.of(context).size.width * .58, | |
child: Text( | |
destinationAddress, | |
overflow: TextOverflow.ellipsis, | |
maxLines: 3, | |
softWrap: true, | |
), | |
), | |
IconButton( | |
// Botão para traçar rota do local atual até o destino | |
icon: Icon(Icons.map_rounded), | |
onPressed: () async { | |
_traceRoute(destinationAddress); | |
}, | |
) | |
], | |
), | |
], | |
), | |
); | |
} | |
Widget _buildButton(ScheduleModel demand) { | |
if (demand.etapa == 3) { | |
return RaisedButton( | |
onPressed: () async { | |
// Aceitando a demanda conforme dados informados | |
final _professionalCubit = context.read<ProfessionalCubit>(); | |
await _professionalCubit.acceptJobRequest( | |
demand, | |
_professionalModel.id, | |
); | |
}, | |
color: customYellowButtonConfirm, | |
textColor: Colors.white, | |
child: Text( | |
"Confirmar", | |
style: TextStyle(fontWeight: FontWeight.bold), | |
), | |
); | |
} | |
return RaisedButton( | |
onPressed: () {}, | |
child: Text(demand.etapaDisplay), | |
); | |
} | |
_showMessage(String message, {bool error = false}) { | |
if (message != null && message.isNotEmpty) { | |
setState(() { | |
_scaffoldKey.currentState.showSnackBar( | |
error == false ? customSuccessSnackbar(message) : customErrorSnackbar(message), | |
); | |
}); | |
} | |
} | |
void _traceRoute(String destination) async { | |
try { | |
List<String> destinations = destination.split("|"); | |
if (destinations.length > 1) { | |
destination = destinations[0]; | |
} | |
if (destinations.length == 1) { | |
destinations = destination.toLowerCase().split("cep"); | |
} | |
if (destinations.length > 1) { | |
destination = destinations[0]; | |
} | |
final location = Location(); | |
final currentLocation = await location.getLocation(); | |
LatLng startPosition = LatLng(currentLocation.latitude, currentLocation.longitude); | |
LatLng endPosition = LatLng(-10.1819276, -48.3398503); | |
MapRoute.traceRoute(startPosition, endPosition, endAddress: destination); | |
} catch (e) {} | |
} | |
_hideKeyboard(BuildContext context) { | |
FocusScope.of(context).requestFocus(FocusNode()); | |
} | |
_makeToast(String texto) async { | |
return showDialog( | |
context: context, | |
builder: (context) { | |
return AlertDialog( | |
title: Text(''), | |
content: Text(texto), | |
actions: <Widget>[ | |
FlatButton( | |
child: Text('Cancelar'), | |
onPressed: () => Navigator.pop(context), | |
), | |
FlatButton( | |
child: Text('Excluir'), | |
onPressed: () {}, | |
) | |
], | |
); | |
}, | |
); | |
} | |
void _loadData() async { | |
final _professionalCubit = context.read<ProfessionalCubit>(); | |
await _professionalCubit.fetchProfessionalDemands(); | |
_professionalModel = _professionalCubit.professionalModel; | |
} | |
Future _refreshData() async { | |
final _professionalCubit = context.read<ProfessionalCubit>(); | |
await _professionalCubit.fetchProfessionalDemands(); | |
_professionalModel = _professionalCubit.professionalModel; | |
} | |
/// Método para construir a imagem circular da demanda | |
Widget _buildDemandCircularImage(ScheduleModel demand) { | |
try { | |
if (demand.fkCliente.clientHasPicture == true) { | |
return Padding( | |
padding: const EdgeInsets.only(right: 10.0), | |
child: _buildProfileImage(demand.fkCliente.foto), | |
); | |
} else { | |
return Padding( | |
padding: const EdgeInsets.only(right: 10.0), | |
child: _buildProfileImageAsset(), | |
); | |
} | |
} catch (e) { | |
return _buildProfileImageAsset(); | |
} | |
} | |
/// Método para construir o botão de rejeição da demanda | |
Widget _buildRejectButton(ScheduleModel demand) { | |
try { | |
return Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: [ | |
// Botão para aceitar a demanda | |
_buildButton(demand), | |
// Botão para informar que estou chegou no destino | |
Visibility( | |
visible: demand.demandIsAccept, | |
child: _buildButtonComePlace(demand), | |
), | |
FlatButton( | |
onPressed: () async { | |
// Rejeitando a demanda conforme dados informados | |
final _professionalCubit = context.read<ProfessionalCubit>(); | |
await _professionalCubit.rejectJobRequest(demand); | |
}, | |
child: Text("Rejeitar"), | |
) | |
], | |
); | |
} catch (e) { | |
return Container(); | |
} | |
} | |
/// Método para construir a área com o valor do da demanda | |
Widget _buildDemandTicket(ScheduleModel demand) { | |
try { | |
return Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text( | |
"Valor do Serviço", | |
style: TextStyle( | |
color: customTextBlueCardText, | |
), | |
), | |
Text( | |
formatRealPattern.format(demand.fkServico.valor), | |
style: TextStyle( | |
color: customTextBlueCardText, | |
fontSize: 18, | |
fontWeight: FontWeight.bold, | |
), | |
), | |
], | |
); | |
} catch (e) { | |
return Container(); | |
} | |
} | |
Widget _buildDemandDataFilterArea(ScheduleModel demand) { | |
try { | |
return Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text( | |
"Dados da demanda", | |
style: TextStyle( | |
color: Color(0xffA1A4A6), | |
), | |
), | |
Visibility( | |
visible: demand.enderecoAtendimento.isNotEmpty, | |
child: Column( | |
children: [ | |
SizedBox(height: 12), | |
Text(demand.enderecoAtendimento), | |
], | |
), | |
), | |
Visibility( | |
visible: demand.fkServico.getHoraAula != null && demand.fkServico.getHoraAula.isNotEmpty, | |
child: Column( | |
children: [ | |
SizedBox(height: 6), | |
Text(demand.fkServico.getHoraAula), | |
], | |
)), | |
Visibility( | |
visible: demand.fkServico.getLocalAtendimento != null && demand.fkServico.getLocalAtendimento.isNotEmpty, | |
child: Column( | |
children: [ | |
SizedBox(height: 6), | |
Text(demand.fkServico.getLocalAtendimento), | |
], | |
)), | |
Visibility( | |
visible: demand.fkServico.getLocalServico != null && demand.fkServico.getLocalServico.isNotEmpty, | |
child: Column( | |
children: [ | |
SizedBox(height: 6), | |
Text(demand.fkServico.getLocalServico), | |
], | |
)), | |
Visibility( | |
visible: demand.fkServico.getPotenciaArCondicionado != null && | |
demand.fkServico.getPotenciaArCondicionado.isNotEmpty, | |
child: Column( | |
children: [ | |
SizedBox(height: 6), | |
Text(demand.fkServico.getPotenciaArCondicionado), | |
], | |
)), | |
Visibility( | |
visible: demand.fkServico.getTipoPiscina != null && demand.fkServico.getTipoPiscina.isNotEmpty, | |
child: Column( | |
children: [ | |
SizedBox(height: 6), | |
Text(demand.fkServico.getTipoPiscina), | |
], | |
)), | |
Visibility( | |
visible: demand.fkServico.getTamanhoJardim != null && demand.fkServico.getTamanhoJardim.isNotEmpty, | |
child: Column( | |
children: [ | |
SizedBox(height: 6), | |
Text(demand.fkServico.getTamanhoJardim), | |
], | |
)), | |
], | |
); | |
} catch (e) { | |
return Container(); | |
} | |
} | |
Widget _buildDescriptionServiceArea(ScheduleModel demand) { | |
try { | |
return Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text( | |
"Descrição do Serviço", | |
style: TextStyle( | |
color: Color(0xffA1A4A6), | |
), | |
), | |
SizedBox(height: 4), | |
Text(demand.fkServico.description), | |
SizedBox(height: 12), | |
Text( | |
"Serviço", | |
style: TextStyle( | |
color: Color(0xffA1A4A6), | |
), | |
), | |
SizedBox(height: 4), | |
Text(demand.fkServico.nome), | |
], | |
); | |
} catch (e) { | |
return Container(); | |
} | |
} | |
Widget _buildProfileImageAsset() { | |
try { | |
return Container( | |
width: Util.getProportionScreenHeight(context, 0.05), | |
height: Util.getProportionScreenHeight(context, 0.05), | |
child: Image.asset( | |
'assets/icons/user.png', | |
fit: BoxFit.contain, | |
), | |
); | |
} catch (e) { | |
return Container(); | |
} | |
} | |
Widget _buildProfileImage(String imageProfile) { | |
try { | |
return CachedNetworkImage( | |
imageUrl: imageProfile, | |
imageBuilder: (context, imageProvider) => Container( | |
decoration: BoxDecoration( | |
image: DecorationImage( | |
image: imageProvider, | |
fit: BoxFit.cover, | |
alignment: Alignment.topCenter, | |
colorFilter: ColorFilter.mode( | |
Colors.white24, | |
BlendMode.colorDodge, | |
), | |
), | |
), | |
), | |
placeholder: (context, url) => CircularProgressIndicator(), | |
errorWidget: (context, url, error) => Container(), | |
); | |
} catch (e) { | |
return _buildProfileImageAsset(); | |
} | |
} | |
Widget _buildButtonComePlace(ScheduleModel demand) { | |
return RaisedButton( | |
color: customBlueDark, | |
onPressed: () {}, | |
child: Text( | |
"Cheguei", | |
style: TextStyle( | |
color: Colors.white, | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment