Skip to content

fix: pass resolved therapist ID and time slot to Supabase on appointment booking#220

Open
Varadraj75 wants to merge 3 commits into
AOSSIE-Org:mainfrom
Varadraj75:fix/appointment-booking-slot-and-therapist-id
Open

fix: pass resolved therapist ID and time slot to Supabase on appointment booking#220
Varadraj75 wants to merge 3 commits into
AOSSIE-Org:mainfrom
Varadraj75:fix/appointment-booking-slot-and-therapist-id

Conversation

@Varadraj75
Copy link
Copy Markdown
Contributor

@Varadraj75 Varadraj75 commented Apr 14, 2026

Closes #219

📝 Description

Three separate bugs in the appointment booking flow caused every booking to be written to Supabase with a midnight timestamp, an empty therapist_id, and the wrong name. The selected time slot was captured in the model but toEntity() always called DateTime.parse(date) on a date-only string. therapistId was hardcoded to '' .
name was wired to serviceType instead of appointmentName.

Additionally there were no pre-submission guards - the booking call could fire with a null date, empty slot, or empty therapist ID and either crash or insert garbage. The slot parser had no error handling, so a malformed slot would throw uncaught. The UI had no way to surface what went wrong since catch(e) silently returned false.

🔧 Changes Made

  • Added _therapistId field populated after the availability fetch, passed correctly into the model instead of hardcoded empty string
  • Added _bookingError field and bookingError getter so the UI can display specific error messages instead of silently failing
  • Added isSubmitting getter so the UI can disable the booking button during an in-flight request
  • Added pre-submission validation guards for null date, empty slot, and empty therapist ID with descriptive error messages
  • Added _parseSlotToDateTime() helper that safely parses slot strings like "10:00 AM" into a full DateTime, returns null on any malformed input instead of throwing
  • createAppointment() now checks the parsed DateTime for null and sets a user facing error instead of crashing
  • Fixed name: serviceType to name: appointmentName in toConsultationRequestEntity() so the correct appointment name is stored
  • Added .toLocal() in toEntity() so the timestamp is stored in local time
  • clearSelections() now resets _therapistId, _isSubmitting, and _bookingError alongside existing fields

📷 Screenshots or Visual Changes (if applicable)

Not applicable. The fix is in data written to Supabase, not visible in the UI.

🤝 Collaboration

Collaborated with: NONE

✅ Checklist

  • I have read the contributing guidelines.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if applicable).
  • Any dependent changes have been merged and published in downstream modules.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed appointment name used during booking.
    • Corrected appointment date/time handling to use local timezone.
    • Added clearer error reporting when required booking details are missing or invalid.
  • Improvements

    • Prevented concurrent appointment submissions.
    • Improved booking state tracking and feedback (including therapist association when viewing slots).
    • Better handling and parsing of selected time slots; clearing selections now resets booking state.

Copilot AI review requested due to automatic review settings April 14, 2026 18:14
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 14, 2026

Warning

Rate limit exceeded

@Varadraj75 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 53 minutes and 49 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 53 minutes and 49 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 11d5158e-b546-49b3-b293-7ab79bf737a0

📥 Commits

Reviewing files that changed from the base of the PR and between 2dd0f40 and 28548b8.

📒 Files selected for processing (1)
  • patient/lib/provider/appointments_provider.dart
📝 Walkthrough

Walkthrough

Appointment booking now preserves selected time slots and therapist IDs by parsing slot strings into full DateTime timestamps, propagating the resolved timestamp through model/entity conversion, and adding submission guards, booking error state, and therapistId tracking in the provider.

Changes

Cohort / File(s) Summary
Entity & Model
patient/lib/core/entities/.../patient_schedule_appointment_entity.dart, patient/lib/model/patient_models/patient_schedule_appointment_model.dart
Entity mapping now uses appointmentNameConsultationRequestEntity.name. Model toEntity() parses ISO date and converts to local DateTime via .toLocal() so timestamp preserves timezone.
Appointment Booking Provider
patient/lib/provider/appointments_provider.dart
Added booking state fields and public getters (_therapistId, _isSubmitting, _bookingError); set _therapistId when fetching availability; createAppointment() now guards concurrent submissions, validates inputs with early returns and error messages, parses _selectedTimeSlot into a DateTime via _parseSlotToDateTime(), uses resolved therapistId and slot DateTime for creation, handles errors into _bookingError, resets submitting state, refreshes appointments, and clearSelections() resets new state.

Sequence Diagram(s)

sequenceDiagram
    participant UI as Client/UI
    participant P as AppointmentsProvider
    participant R as AppointmentsRepository
    participant DB as Supabase/API

    UI->>P: schedule request (selectedDate, selectedTimeSlot, service)
    P->>P: validate inputs & guard _isSubmitting
    P->>P: _parseSlotToDateTime(selectedTimeSlot, selectedDate)
    alt parse success
        P->>R: createAppointment(therapistId, resolvedDateTime, service, ...)
        R->>DB: insert session (timestamp = resolvedDateTime, therapist_id)
        DB-->>R: success
        R-->>P: success
        P->>P: refresh appointments, reset _isSubmitting
        P-->>UI: success
    else parse failure or validation error
        P-->>UI: set bookingError, notify listeners
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • jddeep

Poem

🐰 I parsed the slot, no more midnight gloom,
Therapists named, the bookings find room.
Guards stand watch so double taps don't fray,
Timestamps hop true, and errors kept at bay.
✨🕰️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main fix: resolving therapist ID and time slot issues in appointment booking.
Linked Issues check ✅ Passed All coding requirements from issue #219 are met: therapist ID resolution, slot parsing, timestamp persistence, validation guards, and error handling.
Out of Scope Changes check ✅ Passed All changes directly address the appointment booking bugs described in issue #219 with no unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes multiple data-integrity issues in the patient appointment booking flow so that bookings sent to Supabase include the resolved therapist ID, the selected time slot (not midnight), and the correct appointment name, while also surfacing booking errors to the UI and preventing duplicate submissions.

Changes:

  • Add therapist ID tracking + submission/error state to AppointmentsProvider, including slot parsing into a full DateTime.
  • Ensure PatientScheduleAppointmentModel.toEntity() uses a local DateTime when building the entity timestamp.
  • Fix ConsultationRequestEntity.name mapping to use appointmentName instead of serviceType.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
patient/lib/provider/appointments_provider.dart Adds therapist ID propagation, validation + error messaging, submission guard, and slot→DateTime parsing for correct timestamps.
patient/lib/model/patient_models/patient_schedule_appointment_model.dart Updates entity conversion to local time when parsing the timestamp string.
patient/lib/core/entities/patient_entities/patient_schedule_appointment_entity.dart Fixes request mapping to persist the correct appointment name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread patient/lib/provider/appointments_provider.dart Outdated
Comment thread patient/lib/provider/appointments_provider.dart
Comment thread patient/lib/provider/appointments_provider.dart Outdated
Comment thread patient/lib/provider/appointments_provider.dart
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@patient/lib/provider/appointments_provider.dart`:
- Around line 45-47: The booking UI must use the provider's exposed state:
change the create appointment screen to read provider.isSubmitting to disable
the submit button (set onPressed to null or show loading) to prevent duplicate
submissions, and read provider.bookingError to display the specific error
message in the form or beneath the button instead of the generic failure text;
update any submit handler to avoid triggering another submit when
AppointmentsProvider.isSubmitting is true and surface
AppointmentsProvider.bookingError in the UI for user-facing errors.
- Around line 135-138: The code sets _therapistId before verifying the fetch
token, which can leave a stale therapist ID if _availableBookingSlots returns
early or fails; modify the logic in the appointments provider so that
_therapistId is only assigned after the token equality check (_fetchToken)
passes and after _availableBookingSlots completes successfully, or ensure you
clear/reset _therapistId on every early return/failure path inside
_availableBookingSlots so stale IDs are never left in state.
- Around line 287-295: The parser currently allows out-of-range 12-hour inputs
like "13:00 PM" or "00:15 AM" because meridiem-specific bounds aren't enforced;
update the validation around parsedHour/parsedMinute and the meridiem flags
(parsedHour, parsedMinute, isPM, isAM) so that if a meridiem is present
(parts.length > 1) the hour must be in 1..12 and otherwise keep the 0..23 check;
return null immediately for invalid meridiem-hour combos before applying the
12->24 conversion (the existing adjustments to hour for isPM/isAM and the final
DateTime(date.year, date.month, date.day, hour, minute) remain the same).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad6a4229-ecb0-4b8e-ae8c-b22105b0a146

📥 Commits

Reviewing files that changed from the base of the PR and between 051a4f3 and 1d57cfe.

📒 Files selected for processing (3)
  • patient/lib/core/entities/patient_entities/patient_schedule_appointment_entity.dart
  • patient/lib/model/patient_models/patient_schedule_appointment_model.dart
  • patient/lib/provider/appointments_provider.dart

Comment thread patient/lib/provider/appointments_provider.dart
Comment thread patient/lib/provider/appointments_provider.dart Outdated
Comment thread patient/lib/provider/appointments_provider.dart Outdated
…ment, fetchingSlots guard, tighten slot parser, surface ActionResultFailure error message
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
patient/lib/provider/appointments_provider.dart (1)

87-90: ⚠️ Potential issue | 🟠 Major

Clear _therapistId on all early/failure paths to prevent stale therapist bookings.

Line 137 assigns _therapistId only on success, but Line 87 and Line 117 early returns plus Line 147 catch path do not clear prior state. That can leave an old therapist ID and allow booking against the wrong therapist.

Suggested patch
@@
       if (currentUser == null) {
+        _therapistId = '';
         availableTimeSlots = [];
         return;
       }
@@
       if (therapistId == null || therapistId.isEmpty) {
+        _therapistId = '';
         availableTimeSlots = [];
         return;
       }
@@
     } catch(e) {
       print(e);
       if (token == _fetchToken) {
+        _therapistId = '';
         availableTimeSlots = [];
       }
     } finally {

Also applies to: 117-120, 137-138, 145-149

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@patient/lib/provider/appointments_provider.dart` around lines 87 - 90, In the
appointment loading flow in appointments_provider.dart (the method that sets
availableTimeSlots and _therapistId), ensure you clear stale state by assigning
_therapistId = null on all early/failure paths: when currentUser is null (the
branch that sets availableTimeSlots = []), on any other early-return branches
(the path around the check that currently returns before assigning
_therapistId), and inside the catch/failure handler that currently only clears
availableTimeSlots; set _therapistId = null alongside availableTimeSlots = [] so
the provider never retains a stale therapist ID after errors or early exits.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@patient/lib/provider/appointments_provider.dart`:
- Around line 195-205: Before submitting, ensure the currently chosen slot is
still present in the latest available slots: in the booking flow where you check
_selectedTimeSlot, add a validation that _selectedTimeSlot exists in the
collection of availableTimeSlots (e.g., compare by slot id or exact datetime)
and if not set _bookingError to a message like 'Selected time slot is no longer
available.', call notifyListeners(), and return false; apply the same existence
check around the other booking guards that reference
_selectedTimeSlot/_isFetchingSlots (the blocks at 207-211 and 217-223) so you
never proceed with a stale selection.

---

Duplicate comments:
In `@patient/lib/provider/appointments_provider.dart`:
- Around line 87-90: In the appointment loading flow in
appointments_provider.dart (the method that sets availableTimeSlots and
_therapistId), ensure you clear stale state by assigning _therapistId = null on
all early/failure paths: when currentUser is null (the branch that sets
availableTimeSlots = []), on any other early-return branches (the path around
the check that currently returns before assigning _therapistId), and inside the
catch/failure handler that currently only clears availableTimeSlots; set
_therapistId = null alongside availableTimeSlots = [] so the provider never
retains a stale therapist ID after errors or early exits.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5a2c1c5b-dea2-40af-afa1-987878b2043b

📥 Commits

Reviewing files that changed from the base of the PR and between 1d57cfe and 2dd0f40.

📒 Files selected for processing (1)
  • patient/lib/provider/appointments_provider.dart

Comment thread patient/lib/provider/appointments_provider.dart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: Appointment booking ignores selected time slot, every appointment saved at midnight to Supabase

2 participants