fix: compare service days as dates, not raw strings

DateTime.toString() renders "2026-07-13 00:00:00.000Z" while the backend
sends "2026-07-13T00:00:00.000Z", so every day comparison was false and no
booked slot was ever detected. Both calendars showed fully free days.

The client calendar now also treats an unloaded agenda as busy instead of
free: rendering a taken slot as available leads straight to a double booking.

Note: the client still reads /services/professional/calendar, which returns
the *caller's* calendar. There is no endpoint for another professional's
agenda, so a client cannot yet see which of that professional's slots are
taken. That needs a backend endpoint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-24 20:27:40 -05:00
co-authored by Claude Opus 5
parent 2c1ba7f6d5
commit 8c6e2ae024
3 changed files with 26 additions and 8 deletions
@@ -6,6 +6,7 @@ import 'package:intl/intl.dart';
import 'package:professional_repository/professional_repository.dart'; import 'package:professional_repository/professional_repository.dart';
import 'package:prosappco/blocs/service_bloc/service_bloc.dart'; import 'package:prosappco/blocs/service_bloc/service_bloc.dart';
import 'package:prosappco/screens/service/professional_service_screen.dart'; import 'package:prosappco/screens/service/professional_service_screen.dart';
import 'package:prosappco/utils/service_day.dart';
import 'package:prosappco/utils/time_of_day_extension.dart'; import 'package:prosappco/utils/time_of_day_extension.dart';
import 'package:prosappco/utils/time_of_day_utils.dart'; import 'package:prosappco/utils/time_of_day_utils.dart';
import 'package:service_repository/service_repository.dart'; import 'package:service_repository/service_repository.dart';
@@ -596,7 +597,7 @@ class _ProfessionalCalendarScreenState
TimeOfDay time, List<ServiceEntity>? services, DateTime day) { TimeOfDay time, List<ServiceEntity>? services, DateTime day) {
if (services == null) return null; if (services == null) return null;
for (final s in services) { for (final s in services) {
if (day.toString() != s.day || s.range1Hour1 != time) continue; if (!isSameServiceDay(day, s.day) || s.range1Hour1 != time) continue;
if (s.status == ServiceStatus.cancelled || if (s.status == ServiceStatus.cancelled ||
s.status == ServiceStatus.denied) { s.status == ServiceStatus.denied) {
continue; continue;
+10 -7
View File
@@ -5,6 +5,7 @@ import 'package:intl/intl.dart';
import 'package:professional_repository/professional_repository.dart'; import 'package:professional_repository/professional_repository.dart';
import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart'; import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart';
import 'package:prosappco/utils/time_of_day_extension.dart'; import 'package:prosappco/utils/time_of_day_extension.dart';
import 'package:prosappco/utils/service_day.dart';
import 'package:prosappco/utils/time_of_day_utils.dart'; import 'package:prosappco/utils/time_of_day_utils.dart';
import 'package:service_repository/service_repository.dart'; import 'package:service_repository/service_repository.dart';
import 'package:setting_repository/setting_repository.dart'; import 'package:setting_repository/setting_repository.dart';
@@ -233,14 +234,16 @@ class UserCalendarScreenState extends State<UserCalendarScreen> {
bool _isHora1Ocupada( bool _isHora1Ocupada(
TimeOfDay hora1, List<ServiceEntity>? events, DateTime selectedDay) { TimeOfDay hora1, List<ServiceEntity>? events, DateTime selectedDay) {
if (events != null) { // Treat "could not load the agenda" as busy rather than free: showing a
for (ServiceEntity event in events) { // taken slot as available leads straight to a double booking.
if (selectedDay.toString() == event.day) { if (events == null) return true;
if (hora1 == event.range1Hour1) { for (final event in events) {
return true; if (!isSameServiceDay(selectedDay, event.day)) continue;
} if (event.status == ServiceStatus.cancelled ||
} event.status == ServiceStatus.denied) {
continue;
} }
if (hora1 == event.range1Hour1) return true;
} }
return false; return false;
} }
+14
View File
@@ -0,0 +1,14 @@
/// Whether a service's `day` field refers to the same calendar day as [day].
///
/// The backend returns ISO 8601 ("2026-07-13T00:00:00.000Z") while
/// `DateTime.toString()` produces a space separator ("2026-07-13 00:00:00.000Z"),
/// so comparing the two as raw strings never matched and every booked slot
/// rendered as free. Compare parsed calendar dates instead.
bool isSameServiceDay(DateTime day, String? serviceDay) {
if (serviceDay == null || serviceDay.isEmpty) return false;
final parsed = DateTime.tryParse(serviceDay);
if (parsed == null) return false;
return parsed.year == day.year &&
parsed.month == day.month &&
parsed.day == day.day;
}