380 lines
13 KiB
Dart
380 lines
13 KiB
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:injector/injector.dart';
|
|
import 'package:intl_phone_field/helpers.dart';
|
|
import 'package:profession_repository/profession_repository.dart';
|
|
import 'package:professional_repository/professional_repository.dart';
|
|
import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart';
|
|
import 'package:prosappco/screens/lists/city_list_screen.dart';
|
|
import 'package:prosappco/screens/user/user_calendar_screen.dart';
|
|
import 'package:prosappco/screens/user/user_view_profile_screen.dart';
|
|
import 'package:setting_repository/setting_repository.dart';
|
|
import 'package:shimmer/shimmer.dart';
|
|
|
|
class ProfessionalListScreen extends StatefulWidget {
|
|
const ProfessionalListScreen({super.key});
|
|
|
|
@override
|
|
State<ProfessionalListScreen> createState() => _ProfessionalListScreenState();
|
|
}
|
|
|
|
class _ProfessionalListScreenState extends State<ProfessionalListScreen> {
|
|
final _searchController = TextEditingController();
|
|
final professionRepository = Injector.appInstance.get<ProfessionRepository>();
|
|
final settingRepository = Injector.appInstance.get<SettingRepository>();
|
|
|
|
SettingEntity? settings;
|
|
|
|
List<String>? _professions;
|
|
List<String>? _filteredProfessions;
|
|
String? _selectedProfession;
|
|
|
|
bool _isLoading = true;
|
|
|
|
late final ProfessionalListBloc bloc;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
bloc = Injector.appInstance.get<ProfessionalListBloc>();
|
|
bloc.add(const ProfessionalListFetch());
|
|
|
|
_loadSettings();
|
|
_loadProfessions();
|
|
}
|
|
|
|
void _loadSettings() {
|
|
settingRepository.getSettings().then(
|
|
(value) => setState(() {
|
|
settings = value;
|
|
}),
|
|
);
|
|
}
|
|
|
|
void _loadProfessions() {
|
|
professionRepository.getProfessions().then((Professions element) {
|
|
setState(() {
|
|
_professions = element.professions;
|
|
_filteredProfessions = _professions;
|
|
_isLoading = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocProvider<ProfessionalListBloc>(
|
|
create: (context) => bloc,
|
|
child: BlocBuilder<ProfessionalListBloc, ProfessionalListState>(
|
|
builder: (context, state) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
actions: [
|
|
_selectedProfession != null
|
|
? IconButton(
|
|
icon: const Icon(
|
|
Icons.clear,
|
|
color: Colors.red,
|
|
size: 32,
|
|
),
|
|
onPressed: () {
|
|
setState(() {
|
|
_selectedProfession = null;
|
|
});
|
|
},
|
|
)
|
|
: Container()
|
|
],
|
|
title: _selectedProfession != null
|
|
? Text(_selectedProfession!)
|
|
: const Text('Selecciona un profesional'),
|
|
),
|
|
body: Column(
|
|
children: [
|
|
_isLoading
|
|
? _buildShimmerEffect()
|
|
: _selectedProfession == null
|
|
? Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
|
decoration: BoxDecoration(
|
|
border: Border(
|
|
bottom: BorderSide(
|
|
color: Colors.grey[400]!,
|
|
),
|
|
),
|
|
),
|
|
child: DropdownButtonHideUnderline(
|
|
child: DropdownButton<String>(
|
|
isExpanded: true,
|
|
value: _selectedProfession,
|
|
hint: const Text('Seleccione una profesión'),
|
|
items: _filteredProfessions
|
|
?.map((String profession) {
|
|
return DropdownMenuItem<String>(
|
|
value: profession,
|
|
child: Text(profession),
|
|
);
|
|
}).toList(),
|
|
onChanged: (String? newValue) {
|
|
setState(() {
|
|
_selectedProfession = newValue;
|
|
});
|
|
},
|
|
),
|
|
),
|
|
)
|
|
: Container(),
|
|
_selectedProfession != null
|
|
? TextField(
|
|
controller: _searchController,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_searchController.text = value;
|
|
});
|
|
},
|
|
decoration: const InputDecoration(
|
|
hintText: 'Busca un profesional',
|
|
prefixIcon: Icon(Icons.search),
|
|
enabledBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.grey),
|
|
),
|
|
focusedBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.grey),
|
|
),
|
|
),
|
|
)
|
|
: Container(),
|
|
Expanded(
|
|
child: _selectedProfession != null
|
|
? _body(state)
|
|
: const Center(
|
|
child: Text(
|
|
'Agrega los filtros para ver los profesionales'),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
_body(ProfessionalListState state) {
|
|
if (state is ProfessionalListSuccess) {
|
|
final List<UserProfessional> filteredUsers;
|
|
|
|
// TODO: encaso de filtro dañado
|
|
// if (_searchController.text.isNotEmpty) {
|
|
filteredUsers = state.users
|
|
.where((element) => removeDiacritics(element.myUser.name!)
|
|
.toLowerCase()
|
|
.contains(removeDiacritics(_searchController.text.toLowerCase())))
|
|
.where((user) =>
|
|
user.myUser.id != FirebaseAuth.instance.currentUser!.uid)
|
|
.where(
|
|
(user) => user.professionalInfo.profession == _selectedProfession)
|
|
.toList();
|
|
// } else {
|
|
// filteredUsers = state.users
|
|
// // .where((user) => user.myUser.id != FirebaseAuth.instance.currentUser!.uid)
|
|
// .toList();
|
|
// }
|
|
|
|
if (filteredUsers.isEmpty) {
|
|
return const Center(
|
|
child: Text('Ningun profesional coincide con la busqueda'),
|
|
);
|
|
}
|
|
|
|
return ListView.builder(
|
|
itemCount: filteredUsers.length,
|
|
itemBuilder: (BuildContext context, int index) {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
border: Border(
|
|
bottom: BorderSide(color: Colors.grey.withOpacity(0.2)),
|
|
),
|
|
),
|
|
child: ListTile(
|
|
onTap: () async {
|
|
var datos = await Navigator.push(
|
|
context,
|
|
CupertinoPageRoute(
|
|
builder: (context) => UserCalendarScreen(
|
|
userProfessional: filteredUsers[index],
|
|
),
|
|
),
|
|
);
|
|
|
|
if (datos != null) {
|
|
Navigator.pop(context, datos);
|
|
}
|
|
},
|
|
trailing: GestureDetector(
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
CupertinoPageRoute(
|
|
builder: (context) => UserViewProfileScreen(
|
|
userProfessional: filteredUsers[index],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
child: filteredUsers[index].professionalInfo.rate.isEmpty ||
|
|
settings?.tarifas == false
|
|
? const Icon(
|
|
Icons.keyboard_arrow_right,
|
|
color: Colors.black,
|
|
)
|
|
: Column(
|
|
children: [
|
|
const SizedBox(height: 5),
|
|
const Icon(
|
|
Icons.keyboard_arrow_right,
|
|
color: Colors.black,
|
|
),
|
|
Container(
|
|
//fondo azul
|
|
decoration: BoxDecoration(
|
|
color: Colors.blue[200],
|
|
borderRadius: BorderRadius.circular(50),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 6, vertical: 2),
|
|
child: Text(
|
|
'\$${filteredUsers[index].professionalInfo.rate}',
|
|
style: const TextStyle(
|
|
fontSize: 13,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
leading: Container(
|
|
width: 60,
|
|
height: 60,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
image: filteredUsers[index].myUser.picture == null
|
|
? null
|
|
: DecorationImage(
|
|
image: NetworkImage(
|
|
filteredUsers[index].myUser.picture ?? ''),
|
|
fit: BoxFit.contain,
|
|
),
|
|
),
|
|
child: filteredUsers[index].myUser.picture == null
|
|
? Icon(
|
|
CupertinoIcons.person,
|
|
color: Colors.grey.shade400,
|
|
size: 40,
|
|
)
|
|
: null,
|
|
),
|
|
title: Row(
|
|
children: [
|
|
Flexible(
|
|
child: Text(
|
|
'${filteredUsers[index].myUser.name ?? ''}, ',
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
Text(
|
|
filteredUsers[index].professionalInfo.profession,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
subtitle: Text(
|
|
_disponibilidad(filteredUsers[index].professionalInfo),
|
|
style: const TextStyle(
|
|
fontSize: 13,
|
|
color: Colors.blue,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
return Shimmer.fromColors(
|
|
baseColor: Colors.grey[300]!,
|
|
highlightColor: Colors.grey[100]!,
|
|
child: ListView.builder(
|
|
itemCount: 8,
|
|
itemBuilder: (_, __) => Container(
|
|
decoration: BoxDecoration(
|
|
border: Border(
|
|
bottom: BorderSide(color: Colors.grey.withOpacity(0.4)),
|
|
),
|
|
),
|
|
child: ListTile(
|
|
trailing: const Icon(
|
|
Icons.keyboard_arrow_right,
|
|
color: Colors.black,
|
|
),
|
|
leading: Container(
|
|
width: 60,
|
|
height: 60,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey.shade300,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
title: Container(
|
|
width: MediaQuery.of(context).size.width * 0.8,
|
|
height: 20.0,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
subtitle: Container(
|
|
width: MediaQuery.of(context).size.width * 0.3,
|
|
height: 15.0,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
String _disponibilidad(ProfessionalEntity professionalInfo) {
|
|
if (professionalInfo.locationPreferences == LocationPreferences.office) {
|
|
return 'Disponibilidad: en sitio.';
|
|
}
|
|
|
|
if (professionalInfo.locationPreferences == LocationPreferences.delivery) {
|
|
return 'Disponibilidad: domicilio.';
|
|
}
|
|
|
|
return 'Disponibilidad: domicilio, en sitio.';
|
|
}
|
|
|
|
Widget _buildShimmerEffect() {
|
|
return Expanded(
|
|
child: Shimmer.fromColors(
|
|
baseColor: Colors.grey[300]!,
|
|
highlightColor: Colors.grey[100]!,
|
|
child: ListView.builder(
|
|
itemCount: 8,
|
|
itemBuilder: (_, __) => const ListTileShimmer(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|