631 lines
21 KiB
Dart
631 lines
21 KiB
Dart
import 'dart:io';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_animate/flutter_animate.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:injector/injector.dart';
|
|
import 'package:professional_repository/professional_repository.dart';
|
|
import 'package:prosappco/blocs/professional_bloc/professional_bloc.dart';
|
|
import 'package:prosappco/blocs/professional_profile_bloc/professional_profile_bloc.dart';
|
|
import 'package:prosappco/screens/professional/professional_map_screen.dart';
|
|
import 'package:prosappco/screens/professional/professional_schedule_screen.dart';
|
|
import 'package:setting_repository/setting_repository.dart';
|
|
|
|
class ProfessionalProfileScreen extends StatefulWidget {
|
|
const ProfessionalProfileScreen({super.key});
|
|
|
|
@override
|
|
State<ProfessionalProfileScreen> createState() =>
|
|
_ProfessionalProfileScreenState();
|
|
}
|
|
|
|
class _ProfessionalProfileScreenState extends State<ProfessionalProfileScreen> {
|
|
final settingRepository = Injector.appInstance.get<SettingRepository>();
|
|
SettingEntity? settings;
|
|
XFile? _imageFile;
|
|
|
|
bool loadFinish = false;
|
|
|
|
bool officeValue = false;
|
|
bool deliveryValue = false;
|
|
bool rateValue = false;
|
|
|
|
final TextEditingController _addressController = TextEditingController();
|
|
final TextEditingController _aditionalAddressController =
|
|
TextEditingController();
|
|
final TextEditingController _rateController = TextEditingController();
|
|
|
|
Schedules schedules = Schedules.empty;
|
|
bool isInit = false;
|
|
|
|
double _longitudeController = 0;
|
|
double _latitudeController = 0;
|
|
|
|
bool isNequiActive = false;
|
|
bool isDatafonoActive = false;
|
|
bool isTransferActive = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_loadSettings();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_addressController.dispose();
|
|
_aditionalAddressController.dispose();
|
|
_rateController.dispose();
|
|
|
|
super.dispose();
|
|
}
|
|
|
|
void _loadSettings() {
|
|
settingRepository.getSettings().then(
|
|
(value) => setState(() {
|
|
settings = value;
|
|
}),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Perfil Profesional'),
|
|
),
|
|
body: BlocBuilder<ProfessionalBloc, ProfessionalState>(
|
|
builder: (context, state) {
|
|
return Scaffold(
|
|
body: SingleChildScrollView(
|
|
child: content(context, state),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
content(BuildContext context, ProfessionalState state) {
|
|
if (state is LoadedModeProState) {
|
|
if (state.isProModeActive) {
|
|
if (state.proInfo == null) {
|
|
return const Text('Loading...');
|
|
} else {
|
|
if (!isInit) {
|
|
schedules = state.proInfo!.schedules;
|
|
isInit = true;
|
|
}
|
|
|
|
return body(state.proInfo!);
|
|
}
|
|
}
|
|
}
|
|
return const Text('Go back');
|
|
}
|
|
|
|
body(ProfessionalEntity proInfo) {
|
|
if (!loadFinish) {
|
|
_addressController.text = proInfo.address;
|
|
_aditionalAddressController.text = proInfo.aditionalAddress;
|
|
|
|
_longitudeController = proInfo.longitude;
|
|
_latitudeController = proInfo.latitude;
|
|
|
|
isNequiActive = proInfo.paymentMethods.nequi;
|
|
isDatafonoActive = proInfo.paymentMethods.datafono;
|
|
isTransferActive = proInfo.paymentMethods.transferencia;
|
|
|
|
// proInfo.bannerPicture != ''
|
|
// ? _imageFile = XFile(proInfo.bannerPicture)
|
|
// : _imageFile = null;
|
|
|
|
if (proInfo.locationPreferences == LocationPreferences.both) {
|
|
officeValue = true;
|
|
deliveryValue = true;
|
|
} else if (proInfo.locationPreferences == LocationPreferences.office) {
|
|
officeValue = true;
|
|
deliveryValue = false;
|
|
} else if (proInfo.locationPreferences == LocationPreferences.delivery) {
|
|
officeValue = false;
|
|
deliveryValue = true;
|
|
}
|
|
|
|
_rateController.text = proInfo.rate;
|
|
|
|
loadFinish = true;
|
|
}
|
|
|
|
return Column(
|
|
children: [
|
|
pictureWidget(proInfo.bannerPicture, context),
|
|
const Divider(height: 0),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 15),
|
|
child: Column(
|
|
children: [
|
|
Visibility(
|
|
visible: settings?.domicilios ?? false,
|
|
child: Row(
|
|
children: [
|
|
const Expanded(
|
|
child: Text(
|
|
'Servicio a domicilio',
|
|
style: TextStyle(
|
|
fontSize: 17,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
),
|
|
Switch(
|
|
value: deliveryValue,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
deliveryValue = value;
|
|
if (settings?.domicilios == true) {
|
|
deliveryValue = value;
|
|
if (!deliveryValue) {
|
|
officeValue = true;
|
|
}
|
|
} else {
|
|
deliveryValue = false;
|
|
}
|
|
});
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Row(
|
|
children: [
|
|
const Expanded(
|
|
child: Text(
|
|
'Servicio en sitio',
|
|
style: TextStyle(
|
|
fontSize: 17,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
),
|
|
Switch(
|
|
value: officeValue,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
if (settings?.domicilios == true) {
|
|
officeValue = value;
|
|
if (!officeValue) {
|
|
deliveryValue = true;
|
|
}
|
|
} else {
|
|
officeValue = true;
|
|
deliveryValue = false;
|
|
}
|
|
});
|
|
},
|
|
),
|
|
],
|
|
),
|
|
officeValue
|
|
? Column(
|
|
children: [
|
|
TextField(
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.location_on_outlined),
|
|
hintText: 'Dirección',
|
|
),
|
|
controller: _addressController,
|
|
readOnly: true,
|
|
onTap: () async {
|
|
final Map<String, dynamic>? mapInfo =
|
|
await Navigator.push(
|
|
context,
|
|
CupertinoPageRoute(
|
|
builder: (context) =>
|
|
const ProfessionalMapScreen()),
|
|
);
|
|
|
|
if (mapInfo != null) {
|
|
setState(() {
|
|
_addressController.text =
|
|
mapInfo['address'] ?? '';
|
|
_latitudeController =
|
|
mapInfo['latitude'] ?? 0;
|
|
_longitudeController =
|
|
mapInfo['longitude'] ?? 0;
|
|
});
|
|
}
|
|
}),
|
|
TextField(
|
|
controller: _aditionalAddressController,
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.house_outlined),
|
|
hintText: 'Piso / Conjunto / Apartamento',
|
|
),
|
|
),
|
|
],
|
|
)
|
|
.animate()
|
|
.moveY(duration: const Duration(milliseconds: 100))
|
|
: const SizedBox(),
|
|
],
|
|
),
|
|
),
|
|
const Divider(height: 0),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 15),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
const Expanded(
|
|
child: Text(
|
|
'Tarifa',
|
|
style: TextStyle(
|
|
fontSize: 17,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
),
|
|
Switch(
|
|
value: rateValue,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
if (settings?.tarifas == true) {
|
|
rateValue = value;
|
|
} else {
|
|
rateValue = false;
|
|
}
|
|
});
|
|
},
|
|
),
|
|
],
|
|
),
|
|
rateValue
|
|
? TextField(
|
|
controller: _rateController,
|
|
keyboardType: TextInputType.number,
|
|
decoration: const InputDecoration(
|
|
prefixIcon: Icon(Icons.attach_money),
|
|
hintText: 'COP',
|
|
),
|
|
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
|
)
|
|
.animate()
|
|
.moveY(duration: const Duration(milliseconds: 100))
|
|
: const SizedBox(),
|
|
],
|
|
),
|
|
),
|
|
const Divider(height: 0),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15),
|
|
child: Column(
|
|
children: [
|
|
const Padding(
|
|
padding: EdgeInsets.only(bottom: 10),
|
|
child: Text(
|
|
'Metodos de pago',
|
|
style: TextStyle(
|
|
fontSize: 17,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
),
|
|
CheckboxListTile(
|
|
value: isDatafonoActive,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
isDatafonoActive = value!;
|
|
});
|
|
},
|
|
title: const Text('Datafono'),
|
|
),
|
|
CheckboxListTile(
|
|
value: isNequiActive,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
isNequiActive = value!;
|
|
});
|
|
},
|
|
title: const Text('Nequi'),
|
|
),
|
|
CheckboxListTile(
|
|
value: isTransferActive,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
isTransferActive = value!;
|
|
});
|
|
},
|
|
title: const Text('Transferencia bancaria'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Divider(height: 0),
|
|
GestureDetector(
|
|
onTap: () async {
|
|
Schedules? schedules = await Navigator.push(
|
|
context,
|
|
CupertinoPageRoute(
|
|
builder: (context) =>
|
|
ProfessionalScheduleScreen(schedules: this.schedules),
|
|
),
|
|
);
|
|
|
|
if (schedules != null) {
|
|
setState(() {
|
|
this.schedules = schedules;
|
|
});
|
|
}
|
|
},
|
|
child: Table(
|
|
defaultColumnWidth: const IntrinsicColumnWidth(),
|
|
children: [
|
|
TableRow(
|
|
children: [
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: const Text('Lunes'),
|
|
),
|
|
),
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(timeList(schedules.monday, context)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
TableRow(
|
|
children: [
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: const Text('Martes'),
|
|
),
|
|
),
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(timeList(schedules.tuesday, context)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
TableRow(
|
|
children: [
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: const Text('Miercoles'),
|
|
),
|
|
),
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(timeList(schedules.wednesday, context)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
TableRow(
|
|
children: [
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: const Text('Jueves'),
|
|
),
|
|
),
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(timeList(schedules.thursday, context)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
TableRow(
|
|
children: [
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: const Text('Viernes'),
|
|
),
|
|
),
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(timeList(schedules.friday, context)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
TableRow(
|
|
children: [
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: const Text('Sabado'),
|
|
),
|
|
),
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(timeList(schedules.saturday, context)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
TableRow(
|
|
children: [
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: const Text('Domingo'),
|
|
),
|
|
),
|
|
TableCell(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(timeList(schedules.sunday, context)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Divider(
|
|
height: 1,
|
|
thickness: 0.5,
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 10,
|
|
horizontal: 15,
|
|
),
|
|
child: ElevatedButton(
|
|
onPressed: () {
|
|
context.read<ProfessionalProfileBloc>().add(
|
|
UpdateProfessionalProfileInfo(
|
|
address: _addressController.text,
|
|
aditionalAddress: _aditionalAddressController.text,
|
|
latitude: _latitudeController,
|
|
longitude: _longitudeController,
|
|
locationPreferences: officeValue && deliveryValue
|
|
? LocationPreferences.both
|
|
: officeValue && !deliveryValue
|
|
? LocationPreferences.office
|
|
: deliveryValue && !officeValue
|
|
? LocationPreferences.delivery
|
|
: LocationPreferences.office,
|
|
paymentMethods: PaymentMethodEntity(
|
|
datafono: isDatafonoActive,
|
|
nequi: isNequiActive,
|
|
transferencia: isTransferActive,
|
|
),
|
|
schedules: schedules,
|
|
rate: _rateController.text,
|
|
),
|
|
);
|
|
context.read<ProfessionalProfileBloc>().add(
|
|
UpdateProfessionalBannerInfo(fileBanner: _imageFile?.path),
|
|
);
|
|
|
|
ScaffoldMessenger.of(context).clearSnackBars();
|
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
|
content: Text('Información actualizada correctamente'),
|
|
));
|
|
},
|
|
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,
|
|
child: const Text(
|
|
'Guardar',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 18,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget pictureWidget(String? bannerPicture, BuildContext context) {
|
|
final pictureUrl = bannerPicture;
|
|
final pathImageFile = _imageFile?.path;
|
|
|
|
ImageProvider<Object>? imageProvider;
|
|
|
|
if (pathImageFile != null && pathImageFile.isNotEmpty) {
|
|
imageProvider = FileImage(File(pathImageFile));
|
|
} else if (pictureUrl != null && pictureUrl.isNotEmpty) {
|
|
imageProvider = NetworkImage(pictureUrl);
|
|
}
|
|
|
|
return GestureDetector(
|
|
onTap: () async {
|
|
final ImagePicker picker = ImagePicker();
|
|
final XFile? image = await picker.pickImage(
|
|
source: ImageSource.gallery,
|
|
maxHeight: 1000,
|
|
maxWidth: 2000,
|
|
imageQuality: 40,
|
|
);
|
|
|
|
if (image != null) {
|
|
setState(() {
|
|
_imageFile = image;
|
|
});
|
|
}
|
|
},
|
|
child: pictureContainerWidget(imageProvider),
|
|
);
|
|
}
|
|
|
|
Widget pictureContainerWidget(ImageProvider<Object>? imageProvider) {
|
|
final image = imageProvider == null
|
|
? null
|
|
: DecorationImage(
|
|
image: imageProvider,
|
|
fit: BoxFit.cover,
|
|
);
|
|
|
|
final widget = image == null
|
|
? Icon(
|
|
Icons.image_outlined,
|
|
color: Colors.grey.shade400,
|
|
size: 40,
|
|
)
|
|
: null;
|
|
|
|
return Container(
|
|
width: double.infinity,
|
|
height: 200,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
image: image,
|
|
),
|
|
child: widget,
|
|
);
|
|
}
|
|
|
|
String timeList(ScheduleEntity? schedule, BuildContext context) {
|
|
if (schedule == null) {
|
|
return 'No hay horarios';
|
|
}
|
|
if (!schedule.enabled) {
|
|
return 'No hay horarios';
|
|
}
|
|
if (schedule.range1Hour1 == null || schedule.range2Hour2 == null) {
|
|
return 'No hay horarios';
|
|
}
|
|
if (schedule.continuousDay) {
|
|
return '${ScheduleEntity.getFormatTime(schedule.range1Hour1)} a ${ScheduleEntity.getFormatTime(schedule.range2Hour2)}';
|
|
} else {
|
|
if (schedule.range1Hour2 == null || schedule.range2Hour1 == null) {
|
|
return 'No hay horarios';
|
|
}
|
|
|
|
return '${ScheduleEntity.getFormatTime(schedule.range1Hour1)} a ${ScheduleEntity.getFormatTime(schedule.range1Hour2)} - ${ScheduleEntity.getFormatTime(schedule.range2Hour1)} a ${ScheduleEntity.getFormatTime(schedule.range2Hour2)}';
|
|
}
|
|
}
|
|
}
|