Commit Graph
23 Commits
Author SHA1 Message Date
Lizandro GuarnizoandClaude Opus 5 6cb2755858 fix(booking): read the live agenda and re-check the slot before confirming
/services/public-calendar also returns the professional's current opening
hours; the client threw them away and drew the day from the snapshot the
search list carried, which can be days old. It now uses the fresh ones.

Between picking an hour and pressing "Pedir cita" another patient can
take the slot. The confirm step asks the agenda again and, if the hour is
gone, says so and clears the selection instead of creating a service the
professional would have to deny. A failed re-check lets the booking
through: a network hiccup should not block a patient.

Also:
- tapping a busy slot with no id explains itself instead of doing nothing
- the profile refuses to save an empty rate with the rate switch on,
  which was reaching the backend as rate: ''

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:21:08 -05:00
Lizandro GuarnizoandClaude Opus 5 0a8e5d11a2 fix(agenda): one slot generator for professional and patient
The two calendars each built their own list of hours. The patient's
enforced a 3-hour booking lead time; the professional's did not, so at
15:00 an 08:00-18:00 agenda reported "3 libres" (15, 16, 17) that no
patient could actually take.

Both now go through SlotGenerator. The professional still sees the
near-term hours (blocking the next hour is legitimate) but they are
labelled "Sin reserva" and excluded from the "libres" count, so the
number on his agenda means what the patient sees.

Also in this pass:

- endOf() clamps the slot end at 23:59; a 120-minute slot booked at
  23:00 was sending "25:00" to the backend.
- ScheduleEntity.copyWith can set an hour back to null, so returning a
  day to jornada continua no longer keeps the split hours around.
- Removed the Firebase-era schedule map ('habilitado', 'range1Hour1')
  together with the dead ProfessionalEntity.fromDocument that fed it.
- Settings loads guard on mounted and swallow failures instead of
  calling setState after dispose.
- "Pedir cita" says what is missing instead of doing nothing.

Tests: 9 passing, including the clamp and the empty/inverted ranges.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:17:03 -05:00
Lizandro GuarnizoandClaude Opus 5 0bf96a935d fix(schedules): actually persist the professional's opening hours
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 <noreply@anthropic.com>
2026-08-25 12:52:34 -05:00
Lizandro GuarnizoandClaude Opus 5 7930890d09 fix: clients read the professional's real agenda, not their own
/services/public-calendar/{professionalId} exists after all — the web has been
using it all along. My earlier probes missed it because they guessed the URL
shape, and because it is keyed by the professionals row id rather than the
owning user id, which ProfessionalEntity was discarding.

Adds ProfessionalEntity.recordId and points the client calendar at the public
endpoint. Until now a client browsing a professional's availability was served
their own agenda, so every slot looked free and two people could book the same
hour. A failed load now hides the slots and offers a retry instead of showing
them as available.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 21:29:31 -05:00
Lizandro GuarnizoandClaude Opus 5 8631e6f729 fix: port 7 web features and repair the endless-loading screens
Root cause behind most "stuck loading" reports: the backend changed shape
(schedules became an array, location_preferences a string) while the mobile
parser still hard-cast to Map/int. The TypeError was swallowed by a silent
catch that returned null, and screens only handled the success state, so a
parse failure rendered as a permanent spinner. Same class of bug appeared
across service lists via non-null map lookups and a total absence of
request timeouts.

Ported from prosappweb:
- in-app suggestions (POST /suggestions)
- policies/terms from GET /settings/policies
- configurable appointment length (slot_duration_minutes)
- block/unblock calendar slots (POST /services/block)
- GPS city detection on the profile (Nominatim)
- server-side professional search with haversine distance
- retry cooldown after a rejected professional application

Reliability:
- parse schedules array (day_of_week 0=Mon) and string location_preferences
- read times as wall clock, so 08:00 stays 08:00 across timezones
- carry minutes into hours in TimeOfDay.add; a minute-based step used to
  loop forever and freeze the calendar (covered by test/time_slots_test.dart)
- semver update check instead of string equality, which blocked every build
  that did not exactly match the configured version
- request timeouts across all repositories
- surface HTTP >= 400 instead of reporting failed writes as success
- error states with retry instead of an indefinite shimmer

Includes pre-existing uncommitted work from the UI redesign.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:45:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 90aab51a26 fix: remove Firebase repository exports from all 8 package barrel files
Deleted firebase_*_repository.dart files were still re-exported, causing
compile errors. Barrel files now only export the API implementations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 12:24:48 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7fb0615169 fix: align Flutter API repositories with backend routes (Fase 3 prep)
- api_service_repository: use correct endpoints (/services/me, /services/professional,
  /professional/requests, /professional/history, /professional/calendar)
  instead of broken /services?userId= query params
- api_service_repository: fix status string↔enum, createService DTO,
  paginated {data,meta} response, stub setProfessionalScored/setUserScored,
  extract professionalId from nested professionals.user_id
- api_score_repository: fix /comments/user/:id and /comments/professional/:id
- api_professional_repository + api_user_repository: handle paginated response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 18:29:47 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 af91e0ba04 chore: remove Firebase dependencies and legacy code (Fase 4)
- Delete all firebase_*_repository.dart files (replaced by api_* equivalents)
- Remove cloud_firestore, firebase_auth, firebase_storage, firebase_core from all package pubspecs
- Remove cloud_firestore from main pubspec.yaml
- Delete firebase_options.dart (no longer referenced)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 18:11:31 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 733384091c feat: migrate prosappco from Firebase to NestJS REST API (Fase 2)
- Replace all Firebase* repositories with Api* repositories using HTTP + SharedPreferences JWT
- Remove Firebase.initializeApp() and firebase_messaging background handler from main.dart
- Update DI (app_di.dart) to inject Api* repositories instead of Firebase* ones
- Replace all Timestamp/cloud_firestore usage with ISO 8601 String dates
- Stub PhoneVerificationService (Firebase phone OTP → backend OTP when implemented)
- Add ApiService singleton with JWT management in lib/services/
- Legacy firebase_*_repository.dart files preserved for Fase 4 cleanup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:53:11 -05:00
Felipe 726cf12fd2 fix: campo rate preferences 2024-12-23 09:22:32 -05:00
Felipe 6e1409f4b8 pdf 2024-05-29 16:13:41 -05:00
Felipe f1b2497c92 update faltan los ifs 2024-05-24 17:53:12 -05:00
Felipe bfe782e47e historial y pendientes 2024-04-06 20:50:37 -05:00
Felipe df9f44a8f2 lista de servicios 2024-04-05 18:40:17 -05:00
Felipe e82c7c3afd services 2024-04-05 11:56:45 -05:00
Felipe f46450e5db datos para el servicio 2024-04-03 10:58:46 -05:00
Felipe d7fe33cf30 horario del profesional 2024-03-27 16:42:50 -05:00
Felipe fca6d41ad8 info pro 2024-03-24 14:54:21 -05:00
Felipe f37f8c89c2 horario pro 2024-03-19 22:00:48 -05:00
Felipe 10536be873 actualiza todos los campos excepto schedule 2024-03-19 15:40:07 -05:00
Felipe bb840260ba pro info 2024-03-18 17:46:03 -05:00
Felipe e5a8221edf pdfs 2024-03-15 16:55:01 -05:00
Felipe a3c50cf2c8 form pro - sin imagenes 2024-03-14 22:07:46 -05:00