From 0bf96a935df9e099207f5068b2f77b73de80d63e Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 25 Aug 2026 12:52:34 -0500 Subject: [PATCH] fix(schedules): actually persist the professional's opening hours MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Saving opening hours from the app never did anything. The payload went to PATCH /professionals/me as a map keyed by day name ({"monday": {"habilitado": true, "range1Hour1": "8:0"}}), and that endpoint silently drops a `schedules` key — it answers 200 with the record unchanged. So the professional edited their hours, got "Información actualizada correctamente", and the agenda kept whatever it had. The real endpoint is PATCH /professionals/me/schedules and it takes an array of {day_of_week, enabled, continuous_day, range*_hour*} with zero-padded times, which is what the web has been sending all along. Verified against the backend: the previous payload returns 200 and changes nothing; the new one returns 200 and the rows come back updated. Co-Authored-By: Claude Opus 5 --- .../lib/src/entities/schedule_entity.dart | 27 +++++++++++++++---- .../lib/src/entities/schedules.dart | 18 +++++++++++++ .../api_professional_repository.dart | 8 +++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/packages/professional_repository/lib/src/entities/schedule_entity.dart b/packages/professional_repository/lib/src/entities/schedule_entity.dart index 3cf4175..309882b 100644 --- a/packages/professional_repository/lib/src/entities/schedule_entity.dart +++ b/packages/professional_repository/lib/src/entities/schedule_entity.dart @@ -90,11 +90,28 @@ class ScheduleEntity extends Equatable { }; } - String? formatTimeOfDay(TimeOfDay? time) { - if (time != null) { - return "${time.hour.toString()}:${time.minute.toString()}"; - } - return null; + String? formatTimeOfDay(TimeOfDay? time) => formatTimePadded(time); + + /// "08:05", never "8:5" — the backend matches /^\d{2}:\d{2}$/. + static String? formatTimePadded(TimeOfDay? time) { + if (time == null) return null; + final h = time.hour.toString().padLeft(2, '0'); + final m = time.minute.toString().padLeft(2, '0'); + return '$h:$m'; + } + + /// The row shape PATCH /professionals/me/schedules expects. + /// [dayOfWeek] is 0 = Monday … 6 = Sunday, the backend's own convention. + Map toScheduleDto(int dayOfWeek) { + return { + 'day_of_week': dayOfWeek, + 'enabled': enabled, + 'continuous_day': continuousDay, + 'range1_hour1': formatTimePadded(range1Hour1), + 'range1_hour2': formatTimePadded(range1Hour2), + 'range2_hour1': formatTimePadded(range2Hour1), + 'range2_hour2': formatTimePadded(range2Hour2), + }; } static String? getFormatTime(TimeOfDay? time) { diff --git a/packages/professional_repository/lib/src/entities/schedules.dart b/packages/professional_repository/lib/src/entities/schedules.dart index d7ff84f..de0b4a3 100644 --- a/packages/professional_repository/lib/src/entities/schedules.dart +++ b/packages/professional_repository/lib/src/entities/schedules.dart @@ -63,6 +63,24 @@ class Schedules extends Equatable { ); } + /// The array PATCH /professionals/me/schedules expects, ordered + /// 0 = Monday … 6 = Sunday. + /// + /// The map form below is NOT accepted by the backend: sending it to + /// /professionals/me returns 200 and silently discards the schedules, which + /// is why editing opening hours appeared to work and never persisted. + List> toSchedulesArray() { + return [ + monday.toScheduleDto(0), + tuesday.toScheduleDto(1), + wednesday.toScheduleDto(2), + thursday.toScheduleDto(3), + friday.toScheduleDto(4), + saturday.toScheduleDto(5), + sunday.toScheduleDto(6), + ]; + } + Map toJson() { return { 'monday': monday.toJson(), diff --git a/packages/professional_repository/lib/src/repositories/api_professional_repository.dart b/packages/professional_repository/lib/src/repositories/api_professional_repository.dart index 62e6316..206d9fc 100644 --- a/packages/professional_repository/lib/src/repositories/api_professional_repository.dart +++ b/packages/professional_repository/lib/src/repositories/api_professional_repository.dart @@ -234,6 +234,9 @@ class ApiProfessionalRepository { PaymentMethodEntity paymentMethods, { int slotDurationMinutes = 120, }) async { + // Two calls on purpose: /professionals/me ignores a `schedules` key + // (returns 200 and drops it), and the schedules endpoint takes the array + // form. Sending them together is what made saving opening hours a no-op. await _patch('/professionals/me', { 'address': address, 'aditional_address': aditionalAddress, @@ -242,11 +245,14 @@ class ApiProfessionalRepository { 'location_preferences': enumToInt(locationPreferences), 'latitude': latitude, 'longitude': longitude, - 'schedules': schedules.toJson(), 'payment_methods': paymentMethods.toDocument(), 'slot_duration_minutes': slotDurationMinutes, }); + await _patch('/professionals/me/schedules', { + 'schedules': schedules.toSchedulesArray(), + }); + if (_proInfo != null) { await updateFromFirebase(userId: _proInfo!.id); }