374 lines
12 KiB
Dart
374 lines
12 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:injector/injector.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:professional_repository/professional_repository.dart';
|
|
import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart';
|
|
import 'package:prosappco/utils/time_of_day_utils.dart';
|
|
import 'package:service_repository/service_repository.dart';
|
|
import 'package:setting_repository/setting_repository.dart';
|
|
import 'package:table_calendar/table_calendar.dart';
|
|
|
|
class UserCalendarScreen extends StatefulWidget {
|
|
final UserProfessional userProfessional;
|
|
|
|
const UserCalendarScreen({super.key, required this.userProfessional});
|
|
|
|
@override
|
|
State<UserCalendarScreen> createState() => UserCalendarScreenState();
|
|
}
|
|
|
|
class UserCalendarScreenState extends State<UserCalendarScreen> {
|
|
final settingRepository = Injector.appInstance.get<SettingRepository>();
|
|
SettingEntity? settings;
|
|
|
|
DateTime today = DateTime.now();
|
|
DateTime now = DateTime.now();
|
|
late int numDay;
|
|
|
|
CalendarFormat _calendarFormat = CalendarFormat.month;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
today = DateTime.utc(today.year, today.month, today.day);
|
|
numDay = today.weekday;
|
|
|
|
_loadSettings();
|
|
}
|
|
|
|
void _loadSettings() {
|
|
settingRepository.getSettings().then(
|
|
(value) => setState(() {
|
|
settings = value;
|
|
}),
|
|
);
|
|
}
|
|
|
|
void _onDaySelected(DateTime day, DateTime focusedDay) {
|
|
setState(() {
|
|
today = day;
|
|
numDay = today.weekday;
|
|
});
|
|
}
|
|
|
|
void _onFormatChange(CalendarFormat format) {
|
|
setState(() {
|
|
_calendarFormat = format;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
DateTime lastDay = today.add(const Duration(days: 365));
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Calendario'),
|
|
),
|
|
floatingActionButtonLocation: kIsWeb
|
|
? FloatingActionButtonLocation.startFloat
|
|
: FloatingActionButtonLocation.endFloat,
|
|
resizeToAvoidBottomInset: false,
|
|
body: Column(
|
|
children: [
|
|
Container(
|
|
color: const Color.fromARGB(255, 224, 247, 255),
|
|
child: TableCalendar(
|
|
locale: 'es_MX',
|
|
firstDay: DateTime.now(),
|
|
lastDay: lastDay,
|
|
focusedDay: today,
|
|
availableGestures: AvailableGestures.all,
|
|
onDaySelected: _onDaySelected,
|
|
selectedDayPredicate: (day) => isSameDay(day, today),
|
|
calendarFormat: _calendarFormat,
|
|
onFormatChanged: _onFormatChange,
|
|
availableCalendarFormats: const {
|
|
CalendarFormat.month: 'Mes',
|
|
CalendarFormat.week: 'Semana',
|
|
CalendarFormat.twoWeeks: '2 Semanas',
|
|
},
|
|
),
|
|
),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
|
child: Text(
|
|
DateFormat('dd MMMM yyyy', 'es').format(today),
|
|
style: const TextStyle(
|
|
color: Colors.black,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const Divider(
|
|
height: 0,
|
|
),
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
padding: const EdgeInsets.only(bottom: 15),
|
|
child: Column(
|
|
children: [
|
|
..._rangesItems(_getScheduleFromNumDay(numDay)),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
ScheduleEntity? _getScheduleFromNumDay(int numDay) {
|
|
switch (numDay) {
|
|
case 1:
|
|
return widget.userProfessional.professionalInfo.schedules.monday;
|
|
case 2:
|
|
return widget.userProfessional.professionalInfo.schedules.tuesday;
|
|
case 3:
|
|
return widget.userProfessional.professionalInfo.schedules.wednesday;
|
|
case 4:
|
|
return widget.userProfessional.professionalInfo.schedules.thursday;
|
|
case 5:
|
|
return widget.userProfessional.professionalInfo.schedules.friday;
|
|
case 6:
|
|
return widget.userProfessional.professionalInfo.schedules.saturday;
|
|
case 7:
|
|
return widget.userProfessional.professionalInfo.schedules.sunday;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
List<Widget> _rangesItems(ScheduleEntity? schedule) {
|
|
if (schedule == null ||
|
|
schedule.enabled == false ||
|
|
schedule.range1Hour1 == null ||
|
|
schedule.range2Hour2 == null) {
|
|
return [
|
|
const Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 25),
|
|
child: Text("No hay horarios disponibles"),
|
|
)
|
|
];
|
|
}
|
|
|
|
if (schedule.continuousDay) {
|
|
List<TimeOfDay> ranges = TimeOfDayUtils.genRanges(
|
|
schedule.range1Hour1!,
|
|
schedule.range2Hour2!,
|
|
);
|
|
|
|
return rangesItemList(ranges, null);
|
|
}
|
|
|
|
List<TimeOfDay> ranges1 = TimeOfDayUtils.genRanges(
|
|
schedule.range1Hour1!,
|
|
schedule.range1Hour2!,
|
|
);
|
|
List<TimeOfDay> ranges2 = TimeOfDayUtils.genRanges(
|
|
schedule.range2Hour1!,
|
|
schedule.range2Hour2!,
|
|
);
|
|
|
|
return [
|
|
...rangesItemList(ranges1, null),
|
|
...rangesItemList(ranges2, null),
|
|
];
|
|
}
|
|
|
|
bool _isHora1Ocupada(TimeOfDay hora1, List<ServiceEntity>? events) {
|
|
if (events != null) {
|
|
for (ServiceEntity event in events) {
|
|
DateTime time1 = DateTime(
|
|
today.year,
|
|
today.month,
|
|
today.day,
|
|
hora1.hour,
|
|
hora1.minute,
|
|
);
|
|
|
|
if (event.range1Hour1 == time1.toString()) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
List<Widget> rangesItemList(
|
|
List<TimeOfDay> ranges, List<ServiceEntity>? events) {
|
|
return ranges.map((time) {
|
|
if (_isHora1Ocupada(time, events)) {
|
|
return Card(
|
|
elevation: 4,
|
|
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: ListTile(
|
|
onTap: () {
|
|
ScaffoldMessenger.of(context).clearSnackBars();
|
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
|
content: Text('Este horario ya fue ocupado'),
|
|
));
|
|
},
|
|
contentPadding: const EdgeInsets.all(16),
|
|
leading: Container(
|
|
width: 40,
|
|
height: 40,
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [Colors.yellow, Colors.red, Colors.red],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: const Center(
|
|
child: Icon(
|
|
Icons.access_time,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
title: Text(
|
|
time.format(context),
|
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
|
|
),
|
|
subtitle: const Text(
|
|
'Ocupado',
|
|
style: TextStyle(
|
|
color: Colors.red, fontSize: 13, fontWeight: FontWeight.bold),
|
|
),
|
|
trailing: const Icon(
|
|
Icons.arrow_forward_ios,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
);
|
|
} else {
|
|
return Card(
|
|
elevation: 4,
|
|
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: ListTile(
|
|
onTap: () {
|
|
if (settings?.domicilios == true) {
|
|
if (widget.userProfessional.professionalInfo
|
|
.locationPreferences ==
|
|
LocationPreferences.both) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
content: SingleChildScrollView(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
Navigator.pop(context, [
|
|
today,
|
|
time,
|
|
ServiceLocationPreferences.delivery,
|
|
widget.userProfessional,
|
|
]);
|
|
},
|
|
child: const Text('A domicilio'),
|
|
),
|
|
const Divider(color: Colors.black54),
|
|
GestureDetector(
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
Navigator.pop(context, [
|
|
today,
|
|
time,
|
|
ServiceLocationPreferences.office,
|
|
widget.userProfessional,
|
|
]);
|
|
},
|
|
child: const Text('En sitio'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
} else if (widget.userProfessional.professionalInfo
|
|
.locationPreferences ==
|
|
LocationPreferences.delivery) {
|
|
Navigator.pop(context, [
|
|
today,
|
|
time,
|
|
ServiceLocationPreferences.delivery,
|
|
widget.userProfessional,
|
|
]);
|
|
} else {
|
|
Navigator.pop(context, [
|
|
today,
|
|
time,
|
|
ServiceLocationPreferences.office,
|
|
widget.userProfessional,
|
|
]);
|
|
}
|
|
} else {
|
|
Navigator.pop(context, [
|
|
today,
|
|
time,
|
|
ServiceLocationPreferences.office,
|
|
widget.userProfessional,
|
|
]);
|
|
}
|
|
},
|
|
contentPadding: const EdgeInsets.all(16),
|
|
leading: Container(
|
|
width: 40,
|
|
height: 40,
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [Colors.blue, Colors.green],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: const Center(
|
|
child: Icon(
|
|
Icons.access_time,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
title: Text(
|
|
ScheduleEntity.getFormatTime(time) ?? '',
|
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
|
|
),
|
|
subtitle: const Text(
|
|
'Disponible',
|
|
style: TextStyle(
|
|
color: Colors.green,
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
trailing: const Icon(
|
|
Icons.arrow_forward_ios,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}).toList();
|
|
}
|
|
}
|