Skip to content

Fixes: Closes #335#371

Open
Z3DDIEZ wants to merge 16 commits into
Cherry-CIC:mainfrom
Z3DDIEZ:feature-checkout-pickup-point
Open

Fixes: Closes #335#371
Z3DDIEZ wants to merge 16 commits into
Cherry-CIC:mainfrom
Z3DDIEZ:feature-checkout-pickup-point

Conversation

@Z3DDIEZ
Copy link
Copy Markdown

@Z3DDIEZ Z3DDIEZ commented Feb 24, 2026

Description

This PR implements the "Ship to pick-up point" feature for checkout delivery options, resolving all 5 scenarios outlined in the issue spec. It replaces the mock hard-coded InPost locker logic with a dynamic courier and pickup point selection flow.

Key Changes:

  • Created CourierModel and PickupPointModel data structures for extensibility.
  • Refactored CheckoutViewModel to manage state for multiple couriers and their nested pickup points.
  • Updated DeliveryOptions UI to display a list of couriers when "Ship to pick-up point" is selected, and then display the specific lockers/locations when a courier is tapped.
  • Added payload mapping in createOrder to ensure deliveryMethod, courier, and pickupPointId are sent to the backend.
  • Updated checkout_page.dart validation so the "Pay" button cannot be tapped unless a specific pickup point is selected.

Testing Performed

  • Scenario 1: Verified "Ship to pick-up point" radio option is visible alongside "Ship to Home".
  • Scenario 2: Verified selecting the radio option displays the list of Courier Networks.
  • Scenario 3: Verified selecting a courier displays its locations, and selecting a location correctly summarizes the choice on the UI.
  • Scenario 4: Verified the "Pay" button is disabled/blocked if a pickup point is not explicitly selected.
  • Scenario 5: Verified the order payload logs contain deliveryMethod: "pickup_point", courier, and pickupPointId.
    Screenshots of the 3 main flow steps are attached below.
Screenshot_20260224_133849 Screenshot_20260224_135708 Screenshot_20260224_135813

Summary by CodeRabbit

Release Notes

  • New Features
    • Users can now select their preferred courier during checkout
    • Added pickup point selection feature for parcel delivery
    • Enhanced delivery options to support both home delivery and pickup point delivery, giving customers flexibility in choosing how they receive orders

… CourierModel and PickupPointModel- Refactored CheckoutViewModel to support courier selection and payload generation- Updated delivery options UI to allow selecting couriers and their respective pickup points- Added payment validation for pickup point requirements- Removed legacy InPost hardcoding
@Z3DDIEZ
Copy link
Copy Markdown
Author

Z3DDIEZ commented Feb 24, 2026

Hey! Just an FYI on a few minor project-level files that got updated alongside the checkout feature:

While testing locally, the Android build was failing due to some older configurations. To get things compiling smoothly, I included a few small bumps:

Updated the Android Gradle Plugin (AGP) version in
settings.gradle.kts from 8.7.0 to 8.9.1 to keep up with some of the androidx dependencies.

Bumped the Gradle wrapper in
gradle-wrapper.properties to 8.11.1 since the new AGP required it.

Added a quick null-check fallback for flutter.ndkVersion in
app/build.gradle.kts so the build doesn't crash if an NDK version isn't explicitly set in local.properties.
Do let me kow if i overstepped haha!

@CherryCIC CherryCIC self-requested a review February 25, 2026 14:17
@CherryCIC
Copy link
Copy Markdown
Collaborator

CherryCIC commented Feb 25, 2026

Hey @Z3DDIEZ thank you for this PR and for your contribution. I am personally grateful for people like you, willing to put in the legwork and support us in our mission.

This PR is technically mergeable but has several important considerations you should address before merging...

Here's a detailed assessment:

Blocked is fine as this is due to the PR requiring an approval :)


Strengths

  1. Comprehensive Feature Implementation

  2. Good Code Architecture

  3. Validation in Place

  4. UI/UX Improvements


⚠️ Critical Concerns

Action Required: Check branch protection settings and ensure all required checks pass before merging.

2. Android Build Dependency Updates ⚠️

The PR includes Gradle dependency updates:

  • Gradle: 8.10.28.11.1
  • Android AGP: 8.7.08.9.1

Risks:

  • These are non-trivial updates that could introduce compatibility issues
  • No changelog or testing note explaining why these were needed
  • Could break existing builds if not tested on all target API levels

Recommendation: Ensure these were intentional and have been tested on your CI/CD pipeline.

3. Mocked Data Only 📌

The implementation uses hardcoded courier/pickup point data:

final List<PickupPointModel> _nearestPickupPoints = [
  PickupPointModel(...), // hardcoded locations
]

While the issue acknowledges this ("scenario is about capturing courier + pickup point, not yet about calling real courier APIs"), this means:

  • Not production-ready until API integration (Sendcloud mentioned in issue)
  • ⚠️ Backend dependency: Backend must expect the new payload structure with deliveryMethod, courier, pickupPointId

Critical Questions:

  1. Has the backend team been notified of the new order payload structure?
  2. Is the backend ready to handle this?
  3. Are there separate backend issues for Sendcloud API integration?

4. Potential Logic Issue in delivery_options.dart 🐛

In the UI condition check:

if (status.type == StatusType.success || status.type == StatusType.uninitialized) {

This treats uninitialised and success the same way. If the status is truly uninitialized, the nearestPickupPoints getter will return an empty list (no courier selected), which could cause unexpected empty UI states.

5. Missing Error Handling Edge Case

When selectedPickupPoint?.courierId is accessed in order creation, there's a fallback to 'unknown':

"courier": selectedPickupPoint?.courierId ?? 'unknown',

If this reaches the backend as 'unknown', it could cause order processing failures. Better to validate this cannot happen or fail loudly before submission.

6. Legacy Code Paths Not Fully Cleaned

Comments indicate legacy code is kept for "compatibility," but:

  • selectedInpost and setSelectedInpost() are still used internally
  • fetchNearestInPosts() delegates to the new method
  • This creates maintenance burden and potential bugs if old code is accidentally called

🔍 Cross-Repository Impact Assessment

Since I cannot access other repositories in your organization, you need to verify:

  1. Backend Repository (Cherry-CIC/MVP-backend or similar)

    • ✅ Ready for new payload structure?
    • ✅ Updated /orders endpoint to handle delivery object?
    • ✅ Any database migrations needed?
  2. Other Frontend Dependencies

    • Any other features dependent on the old selectedInpost model?
    • Shared components that reference pickup logic?

📋 Pre-Merge Checklist

  • Verify branch protection requirements - Why is PR showing as "blocked"?
  • Backend team confirmation - Have they reviewed this PR? Is backend ready?
  • Android build testing - Test on Android emulators with updated Gradle versions
  • QA sign-off - Has the feature been tested end-to-end (including order submission)?
  • Clarify dependency updates - Document why Gradle/AGP updates were included
  • API integration planning - Sendcloud integration timeline documented?

Final Recommendation

SAFE TO MERGE IF:

  1. Branch protection checks pass (I believe they have!)
  2. Backend team has reviewed and confirmed readiness, @fion21 @MattGoodwin0 @yusuphjoluwasen could potentially help here when they have a second.
  3. All 5 scenarios have been tested with real backend
  4. Android dependency updates are intentional and tested

DO NOT MERGE IF:

  1. Backend has NOT been updated for new payload structure
  2. No QA testing has been done

In short...
The code quality is good, but the feature is incomplete without backend support.

@Z3DDIEZ
Copy link
Copy Markdown
Author

Z3DDIEZ commented Feb 25, 2026

Don't fret, I'm here to help as much as I can. I wanted to know, backend related changes and the qa tests remaining to be done, I don't know if that's beyond the scope of the pr, or not, but I do hope all is well.

If not, feel free to let me know if there's anything else I may need to work on for this issue.

Copy link
Copy Markdown
Collaborator

@MattGoodwin0 MattGoodwin0 left a comment

Choose a reason for hiding this comment

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

If you wouldn't mind just pulling out those three gradle changes, that would be great!

Rest of the PR looks perfect, thank you for that.

I think it would be safer to make gradle changes separately.

@Z3DDIEZ
Copy link
Copy Markdown
Author

Z3DDIEZ commented Mar 6, 2026

If you wouldn't mind just pulling out those three gradle changes, that would be great!

Rest of the PR looks perfect, thank you for that.

I think it would be safer to make gradle changes separately.

Done! I've reverted the gradle bumps so this PR is strictly focused on the pickup point logic.

@Z3DDIEZ Z3DDIEZ closed this Mar 6, 2026
@Z3DDIEZ Z3DDIEZ reopened this Mar 6, 2026
CherryCIC
CherryCIC previously approved these changes Mar 11, 2026
Copy link
Copy Markdown
Collaborator

@CherryCIC CherryCIC left a comment

Choose a reason for hiding this comment

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

5 new files modified/added:

  1. New Models (clean, well-structured):

    • CourierModel - Simple data class with id, name, JSON serialization
    • PickupPointModel - Extended from InpostModel with courier linking
  2. CheckoutViewModel - Properly refactored:

    • Added courier/pickup point state management
    • Maintains backward compatibility with legacy selectedInpost
    • Both new and old methods sync state correctly
    • Proper payload mapping with deliveryMethod, courier, pickupPointId
    • Cleaned up hardcoded test data
  3. DeliveryOptions UI Widget - Good flow:

    • Step 1: Show courier list
    • Step 2: Show pickup points filtered by selected courier
    • Step 3: Show selected point summary
    • Fixed null safety issues (?.isNotEmpty == true)
    • Removed problematic postcode requirement
  4. CheckoutPage Validation - Updated correctly:

    • Pay button now checks selectedPickupPoint instead of selectedInpost
    • Properly blocks checkout if no pickup point selected
  5. Tests Complete:

    • All 5 scenarios verified with screenshots
    • Gradle changes were reverted (as you requested)

Why It's Safe

Scope-focused - Only touches checkout delivery flow
Backward compatible - Legacy methods still work
State management solid - Proper null resets when changing couriers
Payload correct - Backend-ready delivery details included
Validation enforced - Can't pay without selecting a point
No breaking changes - Only additions and refactoring

From what I can tell... I can approve it. 👍

Thank you.

@CherryCIC
Copy link
Copy Markdown
Collaborator

CherryCIC commented Mar 11, 2026

@MattGoodwin0 do you believe in your professional opinion that the requested changes have been met?

@CherryCIC CherryCIC requested a review from MattGoodwin0 March 16, 2026 16:20
@fion21 fion21 self-requested a review March 24, 2026 20:00
Copy link
Copy Markdown
Collaborator

@fion21 fion21 left a comment

Choose a reason for hiding this comment

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

add this to your codel.yml file, as it s in your repo I dont have access t o it
_____ delete this line above

name: "CodeQL"

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '0 3 * * *'

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read

steps:
  - name: Checkout repository
    uses: actions/checkout@v5

  - name: Initialize CodeQL
    uses: github/codeql-action/init@v4
    with:
      languages: actions

  - name: Perform CodeQL Analysis
    uses: github/codeql-action/analyze@v4

@CherryCIC
Copy link
Copy Markdown
Collaborator

CherryCIC commented Mar 25, 2026

@fion21 thank you for pointing this out. @Z3DDIEZ let me know how you get on mate. Happy to support where I can.

@Z3DDIEZ Z3DDIEZ requested a review from fion21 March 25, 2026 07:18
@Z3DDIEZ
Copy link
Copy Markdown
Author

Z3DDIEZ commented Mar 25, 2026

@CherryCIC done as instructed!

@CherryCIC
Copy link
Copy Markdown
Collaborator

All 4 conflicting files in PR #371 ("Fixes: Closes #335") have been successfully resolved and the merge commit has been committed.

Here's a summary of the decisions made for each file: [github](#371)

1. .github/workflows/codeql.yml (1 conflict)

  • Both sides had identical content (uses: github/codeql-action/analyze@v4) — accepted incoming change from main. No functional difference.

2. lib/features/checkout/checkout_page.dart (1 conflict)

  • Accepted current (feature branch): The canPay variable includes the critical selectedPickupPoint != null check — the core validation of the PR's "Ship to pick-up point" feature.
  • Also manually edited the onPressed: reference on line 188 from canAttemptPayment (main's variable name) to canPay to match the accepted variable.

3. lib/features/checkout/checkout_view_model.dart (3 conflicts)

  • Conflict 1 — Accepted current (feature branch): Preserves the _couriers, _nearestPickupPoints, selectedCourier, selectedPickupPoint data structures — the entire pickup point feature model.
  • Conflict 2 — Accepted incoming (main): The real API implementation checkoutRepository.fetchNearestInposts(postalCode) is used over the feature branch's simulated mock delay (the mock was clearly a placeholder).
  • Conflict 3 — Accepted current (feature branch): Keeps both selectedInpost and selectedPickupPoint being hydrated from Firestore — essential for restoring the user's previously selected pickup point.

4. lib/features/checkout/widgets/delivery_options.dart (1 conflict)

  • Accepted incoming (main): (vm.deliveryChoice ?? '').isNotEmpty is more idiomatic Dart null safety vs. the branch's vm.deliveryChoice?.isNotEmpty == true. Both are functionally equivalent, but the main version is cleaner.

The PR now has no merge conflicts and is ready for review/merge. It preserves the full "Ship to pick-up point" feature including courier selection, pickup point listing, and pay button validation. [github](#371)

I think it is ok to merge now @Z3DDIEZ

@fion21 @MattGoodwin0 thanks for your support on this guys, another quick opinion if you can would be much appreciated for this one before merge.

@CherryCIC CherryCIC self-requested a review April 1, 2026 23:36
CherryCIC
CherryCIC previously approved these changes Apr 1, 2026
Copy link
Copy Markdown
Collaborator

@CherryCIC CherryCIC left a comment

Choose a reason for hiding this comment

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

I approve this PR after resolving the conflicts, but would value another opinion/ review before merging.

@CherryCIC CherryCIC requested a review from JaseElder April 9, 2026 19:01
@CherryCIC
Copy link
Copy Markdown
Collaborator

Sorry to overwhelm you @JaseElder if I am but can I get a second review on this please so we can merge it? Moderate priority on this one.

@JaseElder
Copy link
Copy Markdown
Contributor

JaseElder commented Apr 9, 2026 via email

@CherryCIC
Copy link
Copy Markdown
Collaborator

Thanks Jason. I will be around throughout the day. Give me a call at a time that feels convenient for you and if I can't catch you I'll call you back. @JaseElder

Copy link
Copy Markdown
Contributor

@JaseElder JaseElder left a comment

Choose a reason for hiding this comment

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

This PR has had the erroneous changes from the PR #369 which was merged into main, merged into it. So it will need to merge the revert PR (#403) once that has been merged into main.

Comment thread lib/features/checkout/checkout_view_model.dart
The refactor to _nearestPickupPoints removed the _nearestInpost
declaration, but it was still referenced in fetchNearestPickupPoints()
(lines 387, 411) and by checkout_view_model_test.dart. This restores
the field and its public getter to fix the compile error and unbreak
the test suite.

Addresses review feedback from @JaseElder.
Copy link
Copy Markdown
Contributor

@JaseElder JaseElder left a comment

Choose a reason for hiding this comment

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

Found a couple of issues stopping the app from compiling.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

isLoading isn't declared anywhere.

AppStrings.checkoutPaymentMethodRequired;
});

await showModalBottomSheet<PaymentType>(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing an import for PaymentType

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good day, fixed via my latest commit. Do let me know if theres anything else you would like me to handle!

@CherryCIC
Copy link
Copy Markdown
Collaborator

@Z3DDIEZ Hi mate. Would you like any support with this?

@Z3DDIEZ
Copy link
Copy Markdown
Author

Z3DDIEZ commented Apr 17, 2026

@CherryCIC I would love some, currently I'm indisposed and very far from any computers, unavailable for at least 2 weeks, heading somewhere remote.

@CherryCIC
Copy link
Copy Markdown
Collaborator

Where would you like support?

@CherryCIC CherryCIC self-requested a review April 25, 2026 09:38
@CherryCIC
Copy link
Copy Markdown
Collaborator

I have resolved the core issues blocking the merge.

This PR adds the “Ship to pick-up point” checkout option for #335, replacing hard-coded InPost locker logic with a courier and pickup point selection flow.

It appears to meet the acceptance criteria: users can choose pickup delivery, select a courier and location, see a summary, are blocked from paying until a pickup point is selected, and the order payload includes the delivery method, courier, and pickup point ID.

However, it is not merge-ready because reviewers have flagged compilation issues, plus there may be unrelated Gradle/CodeQL changes inherited from other work.

Next step: fix the build errors, strip out unrelated changes, confirm the backend payload shape, then re-request review.

@Z3DDIEZ

@Z3DDIEZ
Copy link
Copy Markdown
Author

Z3DDIEZ commented Apr 26, 2026

@CherryCIC I was away, deep in the mountains, away from all forms of tech and network connection.
Will get to it as soon as possible!

Z3DDIEZ added 2 commits April 26, 2026 13:22
- Add missing import for PaymentType enum used in showModalBottomSheet
- Replace undeclared `isLoading` variable with
  `viewModel.createOrderStatus.type == StatusType.loading`

Addresses review feedback from JaseElder in PR Cherry-CIC#371.
@Z3DDIEZ Z3DDIEZ requested a review from JaseElder April 26, 2026 11:37
@CherryCIC
Copy link
Copy Markdown
Collaborator

Amazing news @Z3DDIEZ ! I hope you had a nice time. Where abouts did you go?

@CherryCIC
Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR refactors the checkout delivery flow to support courier-managed pickup points. New data models (CourierModel, PickupPointModel) replace direct inpost references. The view model adds courier/pickup-point selection state, a new fetchNearestPickupPoints API, and order creation logic that includes delivery details. The UI updates to show a multi-step selection flow and the page improves initialization safety.

Changes

Courier and Pickup Point Selection Flow

Layer / File(s) Summary
Data Models
lib/core/models/courier_model.dart, lib/core/models/pickup_point_model.dart
New CourierModel (id, name) and PickupPointModel (id, name, address, postcode, lat, long, courierId) with JSON serialization.
View Model State & Methods
lib/features/checkout/checkout_view_model.dart
Adds couriers list, selectedCourier, selectedPickupPoint state; new setSelectedCourier() and setSelectedPickupPoint() setters; fetchNearestPickupPoints() method that filters by selected courier; Firestore hydration updated to populate both legacy and new selection fields.
Order Creation
lib/features/checkout/checkout_view_model.dart
createOrder() builds deliveryDetails map describing pickup-vs-ship-to-home delivery with courier and point identifiers; order payload includes new delivery section.
Page Initialization & Lifecycle
lib/features/checkout/checkout_page.dart
View model initialized as nullable in post-frame callback; listener handlers guard against null; loading indicator driven by createOrderStatus.type; listeners safely removed in dispose().
Delivery Options Widget
lib/features/checkout/widgets/delivery_options.dart
Initialization expansion logic switches from selectedInpost to selectedPickupPoint; pickup selection UI refactored to show courier list first, then pickup points for selected courier; "Change pickup point" resets related state.

Sequence Diagram(s)

The changes introduce a new multi-step courier-driven pickup point selection process. Here is the observable interaction:

sequenceDiagram
  participant User
  participant DeliveryOptions as DeliveryOptions Widget
  participant ViewModel as CheckoutViewModel
  participant API as Pickup Points API
  User->>DeliveryOptions: select Pickup delivery
  DeliveryOptions->>ViewModel: show couriers list
  User->>DeliveryOptions: select courier
  DeliveryOptions->>ViewModel: setSelectedCourier()
  ViewModel->>API: fetchNearestPickupPoints(postal code)
  API-->>ViewModel: nearby points for courier
  DeliveryOptions->>ViewModel: show nearest pickup points
  User->>DeliveryOptions: select pickup point
  DeliveryOptions->>ViewModel: setSelectedPickupPoint()
  ViewModel->>ViewModel: updateDeliveryDetails()
  User->>DeliveryOptions: confirm & pay
  ViewModel->>ViewModel: createOrder(deliveryDetails)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • FRONTEND: Checkout: support “Ship to pick-up point” #335: The PR directly implements the "ship to pick-up point" checkout flow by introducing courier and pickup point models, adding selection state to CheckoutViewModel, and updating the delivery UI to support the multi-step courier-driven selection process.

Poem

🐰 A courier hops into the checkout with grace,
Picking points from the list at just the right place,
From models so new to the UI so bright,
The pickup flow works—a delightful sight!
📦✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title "Fixes: Closes #335" is vague and generic—it references an issue without describing the actual feature or change being implemented. Replace with a descriptive title that summarizes the main feature, e.g., "Implement ship to pick-up point checkout feature" or similar.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

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

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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/workflows/codeql.yml (1)

1-34: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Remove unrelated CodeQL workflow changes from this PR.

This CodeQL workflow modification is unrelated to the "Ship to pick-up point" checkout feature implementation. Mixing infrastructure/CI changes with feature changes makes the PR harder to review, increases merge risk, and violates single-responsibility principles for pull requests.

As noted in the review comments, unrelated changes should be stripped before merging. If the CodeQL/Node24 changes are needed, they should be submitted in a separate PR with appropriate context and testing.

♻️ Recommendation

Revert all changes to .github/workflows/codeql.yml in this PR. If the workflow updates are necessary, create a separate PR specifically for CI/workflow improvements with:

  • Clear justification for the Node24 requirement
  • Evidence that the change doesn't break existing CodeQL scans
  • Appropriate reviewers with CI/infrastructure context
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/codeql.yml around lines 1 - 34, This PR inadvertently
includes unrelated CI changes to the CodeQL workflow
(.github/workflows/codeql.yml); revert the edits so the file returns to its
previous state (remove the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 env addition and
any changes to the analyze job such as the languages: actions block or altered
action versions like github/codeql-action/init@v4), and if Node24 or other
CodeQL updates are actually required, open a separate PR with justification and
tests rather than bundling those changes into the "Ship to pick-up point"
feature PR.
lib/features/checkout/checkout_view_model.dart (1)

374-413: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

fetchNearestPickupPoints does not populate nearestPickupPoints.

This method fetches data and populates _nearestInpost, but the nearestPickupPoints getter (used by the UI) returns from the hardcoded _nearestPickupPoints list. The API results are never surfaced to the new courier-based UI flow.

To connect the data flow, the parsed results should update _nearestPickupPoints (with appropriate courierId mapping), or the getter should read from _nearestInpost with conversion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/checkout_view_model.dart` around lines 374 - 413,
fetchNearestPickupPoints populates _nearestInpost but never updates the
_nearestPickupPoints used by the UI; update the parsed results into
_nearestPickupPoints (or change the nearestPickupPoints getter to return a
mapped view of _nearestInpost). Specifically, inside fetchNearestPickupPoints
after parsing (where parsedInposts is created) map each InpostModel to your
pickup-point representation (assign the appropriate courierId) and replace
_nearestPickupPoints contents (clear/addAll mapped list) so the UI-facing
nearestPickupPoints reflects API results; ensure any code that relies on
courierId uses the mapped value.
🧹 Nitpick comments (2)
lib/features/checkout/checkout_view_model.dart (1)

38-87: 💤 Low value

Hardcoded mock data is not production-ready.

The _couriers and _nearestPickupPoints lists are hardcoded. This is acceptable for development/testing but should be replaced with real API data before production. Consider adding a TODO comment or tracking issue.

Do you want me to open an issue to track the backend integration for couriers and pickup points?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/checkout_view_model.dart` around lines 38 - 87, Replace
the hardcoded mock lists with production data: remove or mark the hardcoded
_couriers and _nearestPickupPoints and add a TODO plus a plan to fetch real data
(e.g., via an injected repository/service) used by the couriers getter and the
nearestPickupPoints getter (which currently filters by selectedCourier);
implement async methods like fetchCouriers() and fetchPickupPoints() that
populate those private lists (or expose streams) and update selectedCourier
handling to work with the real data source; include a clear TODO comment
referencing backend integration so this change is tracked.
lib/features/checkout/widgets/delivery_options.dart (1)

4-4: ⚡ Quick win

Unused import.

fluttertoast is imported but no longer used in this file after the refactor removed the postcode-required toast.

🧹 Remove unused import
-import 'package:fluttertoast/fluttertoast.dart';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/widgets/delivery_options.dart` at line 4, Remove the
unused import of fluttertoast: delete the import line "import
'package:fluttertoast/fluttertoast.dart';" from the top of delivery_options.dart
(the leftover from the removed postcode-required toast) so there are no unused
imports in the file and the analyzer warning disappears.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/core/models/courier_model.dart`:
- Around line 10-15: The CourierModel.fromJson factory currently uses unsafe
casts (id: json['id'] as String, name: json['name'] as String); update it to
defensively parse and validate types: check that json contains keys and that
values are non-null strings (e.g., use runtime type checks or toString
fallbacks) before assigning to the CourierModel constructor, and provide
sensible defaults or throw a clear FormatException when values are
missing/invalid so malformed JSON cannot cause a runtime cast error.

In `@lib/core/models/pickup_point_model.dart`:
- Around line 20-30: The fromJson factory (PickupPointModel.fromJson) currently
uses unsafe casts like json['id'] as String for fields id, name, address,
postcode, lat, long, and courierId which can throw if values are null or not
strings; update this method to defensively parse each value (e.g., check for
null and type, use json['field'] is String ? json['field'] as String : fallback
or convert toString() where appropriate) and provide sensible defaults or throw
a clear FormatException with context if required so missing/invalid backend
values don't cause uncaught TypeErrors at runtime.

In `@lib/features/checkout/checkout_view_model.dart`:
- Around line 443-451: The selectedPickupPoint is being hydrated with a
hardcoded courierId ('inpost') which can misrepresent stored data; update the
hydration in the code that builds PickupPointModel (the selectedPickupPoint
assignment) to read courierId from the Firestore document (use
doc.get(FirestoreConstants.courierId) or a safe default if missing) so
PickupPointModel.courierId reflects the stored value instead of always 'inpost'.
- Around line 585-594: The deliveryDetails construction uses fallback 'unknown'
values when deliveryChoice == 'pickup' but selectedPickupPoint can be null; add
a defensive guard before building deliveryDetails: check deliveryChoice ==
'pickup' and if selectedPickupPoint == null then fail fast (throw an exception,
return an error, or log and abort submission) so you never send courier:
'unknown' or pickupPointId: 'unknown'; update the function that builds/returns
deliveryDetails (referenced by deliveryChoice and selectedPickupPoint) to
perform this validation and handle the error path appropriately.

In `@lib/features/checkout/widgets/delivery_options.dart`:
- Line 298: The branch treating StatusType.uninitialized the same as
StatusType.success causes mock pickup content to render before a fetch; update
the conditional in the widget that checks status.type so it only treats
StatusType.success as the "show results" path (i.e., replace the combined check
in the clause that currently reads "status.type == StatusType.success ||
status.type == StatusType.uninitialized" with a single check for
StatusType.success), and add an explicit branch for StatusType.uninitialized
that renders a prompt/placeholder asking the user to enter a postcode (or
otherwise indicates no data fetched yet) so the UI does not display pickup
lists/points prematurely.
- Around line 356-361: The UI is still bound to the hardcoded
_nearestPickupPoints instead of the API result stored in _nearestInpost, so
tapping a courier updates model._nearestInpost via fetchNearestPickupPoints but
the widgets never read it; update the data flow so the ListTile tap path
(setSelectedCourier, fetchNearestPickupPoints) results are displayed by wiring
the UI to the model.nearestInpost (or merging _nearestInpost into the existing
PickupPointModel list) and ensure showLocker is used to choose which list to
render; specifically change the widgets that currently read _nearestPickupPoints
to prefer model.nearestInpost when non-empty (or after successful fetch), and
keep setSelectedCourier, fetchNearestPickupPoints, nearestInpost,
_nearestInpost, _nearestPickupPoints and showLocker consistent so the fetched
points replace or augment the mock list.

---

Outside diff comments:
In @.github/workflows/codeql.yml:
- Around line 1-34: This PR inadvertently includes unrelated CI changes to the
CodeQL workflow (.github/workflows/codeql.yml); revert the edits so the file
returns to its previous state (remove the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 env
addition and any changes to the analyze job such as the languages: actions block
or altered action versions like github/codeql-action/init@v4), and if Node24 or
other CodeQL updates are actually required, open a separate PR with
justification and tests rather than bundling those changes into the "Ship to
pick-up point" feature PR.

In `@lib/features/checkout/checkout_view_model.dart`:
- Around line 374-413: fetchNearestPickupPoints populates _nearestInpost but
never updates the _nearestPickupPoints used by the UI; update the parsed results
into _nearestPickupPoints (or change the nearestPickupPoints getter to return a
mapped view of _nearestInpost). Specifically, inside fetchNearestPickupPoints
after parsing (where parsedInposts is created) map each InpostModel to your
pickup-point representation (assign the appropriate courierId) and replace
_nearestPickupPoints contents (clear/addAll mapped list) so the UI-facing
nearestPickupPoints reflects API results; ensure any code that relies on
courierId uses the mapped value.

---

Nitpick comments:
In `@lib/features/checkout/checkout_view_model.dart`:
- Around line 38-87: Replace the hardcoded mock lists with production data:
remove or mark the hardcoded _couriers and _nearestPickupPoints and add a TODO
plus a plan to fetch real data (e.g., via an injected repository/service) used
by the couriers getter and the nearestPickupPoints getter (which currently
filters by selectedCourier); implement async methods like fetchCouriers() and
fetchPickupPoints() that populate those private lists (or expose streams) and
update selectedCourier handling to work with the real data source; include a
clear TODO comment referencing backend integration so this change is tracked.

In `@lib/features/checkout/widgets/delivery_options.dart`:
- Line 4: Remove the unused import of fluttertoast: delete the import line
"import 'package:fluttertoast/fluttertoast.dart';" from the top of
delivery_options.dart (the leftover from the removed postcode-required toast) so
there are no unused imports in the file and the analyzer warning disappears.
🪄 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 Plus

Run ID: 5762f0b4-5390-4782-b396-5598cadf641a

📥 Commits

Reviewing files that changed from the base of the PR and between e48e241 and f1b8b74.

📒 Files selected for processing (6)
  • .github/workflows/codeql.yml
  • lib/core/models/courier_model.dart
  • lib/core/models/pickup_point_model.dart
  • lib/features/checkout/checkout_page.dart
  • lib/features/checkout/checkout_view_model.dart
  • lib/features/checkout/widgets/delivery_options.dart

Comment on lines +10 to +15
factory CourierModel.fromJson(Map<String, dynamic> json) {
return CourierModel(
id: json['id'] as String,
name: json['name'] as String,
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Same unsafe casting issue as PickupPointModel.

Apply defensive parsing here as well to avoid runtime crashes from malformed JSON.

🛡️ Proposed fix
  factory CourierModel.fromJson(Map<String, dynamic> json) {
    return CourierModel(
-     id: json['id'] as String,
-     name: json['name'] as String,
+     id: json['id']?.toString() ?? '',
+     name: json['name']?.toString() ?? '',
    );
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
factory CourierModel.fromJson(Map<String, dynamic> json) {
return CourierModel(
id: json['id'] as String,
name: json['name'] as String,
);
}
factory CourierModel.fromJson(Map<String, dynamic> json) {
return CourierModel(
id: json['id']?.toString() ?? '',
name: json['name']?.toString() ?? '',
);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/core/models/courier_model.dart` around lines 10 - 15, The
CourierModel.fromJson factory currently uses unsafe casts (id: json['id'] as
String, name: json['name'] as String); update it to defensively parse and
validate types: check that json contains keys and that values are non-null
strings (e.g., use runtime type checks or toString fallbacks) before assigning
to the CourierModel constructor, and provide sensible defaults or throw a clear
FormatException when values are missing/invalid so malformed JSON cannot cause a
runtime cast error.

Comment on lines +20 to +30
factory PickupPointModel.fromJson(Map<String, dynamic> json) {
return PickupPointModel(
id: json['id'] as String,
name: json['name'] as String,
address: json['address'] as String,
postcode: json['postcode'] as String,
lat: json['lat'] as String,
long: json['long'] as String,
courierId: json['courierId'] as String,
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Unsafe JSON parsing may cause runtime crashes.

The fromJson factory uses direct as String casts without null checks. If the backend returns incomplete data or null values, this will throw a TypeError at runtime.

Consider defensive parsing with fallbacks or explicit null checks:

🛡️ Proposed defensive parsing
  factory PickupPointModel.fromJson(Map<String, dynamic> json) {
    return PickupPointModel(
-     id: json['id'] as String,
-     name: json['name'] as String,
-     address: json['address'] as String,
-     postcode: json['postcode'] as String,
-     lat: json['lat'] as String,
-     long: json['long'] as String,
-     courierId: json['courierId'] as String,
+     id: json['id']?.toString() ?? '',
+     name: json['name']?.toString() ?? '',
+     address: json['address']?.toString() ?? '',
+     postcode: json['postcode']?.toString() ?? '',
+     lat: json['lat']?.toString() ?? '',
+     long: json['long']?.toString() ?? '',
+     courierId: json['courierId']?.toString() ?? '',
    );
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
factory PickupPointModel.fromJson(Map<String, dynamic> json) {
return PickupPointModel(
id: json['id'] as String,
name: json['name'] as String,
address: json['address'] as String,
postcode: json['postcode'] as String,
lat: json['lat'] as String,
long: json['long'] as String,
courierId: json['courierId'] as String,
);
}
factory PickupPointModel.fromJson(Map<String, dynamic> json) {
return PickupPointModel(
id: json['id']?.toString() ?? '',
name: json['name']?.toString() ?? '',
address: json['address']?.toString() ?? '',
postcode: json['postcode']?.toString() ?? '',
lat: json['lat']?.toString() ?? '',
long: json['long']?.toString() ?? '',
courierId: json['courierId']?.toString() ?? '',
);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/core/models/pickup_point_model.dart` around lines 20 - 30, The fromJson
factory (PickupPointModel.fromJson) currently uses unsafe casts like json['id']
as String for fields id, name, address, postcode, lat, long, and courierId which
can throw if values are null or not strings; update this method to defensively
parse each value (e.g., check for null and type, use json['field'] is String ?
json['field'] as String : fallback or convert toString() where appropriate) and
provide sensible defaults or throw a clear FormatException with context if
required so missing/invalid backend values don't cause uncaught TypeErrors at
runtime.

Comment on lines +443 to +451
selectedPickupPoint = PickupPointModel(
id: doc.get(FirestoreConstants.id),
name: doc.get(FirestoreConstants.name),
address: doc.get(FirestoreConstants.address),
postcode: doc.get(FirestoreConstants.postcode),
lat: doc.get(FirestoreConstants.lat),
long: doc.get(FirestoreConstants.long),
courierId: 'inpost',
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Hardcoded courierId: 'inpost' may be incorrect for non-InPost lockers.

When hydrating selectedPickupPoint from Firestore, courierId is hardcoded to 'inpost'. If the user previously selected a different courier's pickup point, this would assign the wrong courier.

Consider storing and retrieving courierId from Firestore:

🛡️ Suggested fix
        selectedPickupPoint = PickupPointModel(
          id: doc.get(FirestoreConstants.id),
          name: doc.get(FirestoreConstants.name),
          address: doc.get(FirestoreConstants.address),
          postcode: doc.get(FirestoreConstants.postcode),
          lat: doc.get(FirestoreConstants.lat),
          long: doc.get(FirestoreConstants.long),
-         courierId: 'inpost',
+         courierId: doc.data()?.containsKey('courierId') == true 
+             ? doc.get('courierId') 
+             : 'inpost',
        );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
selectedPickupPoint = PickupPointModel(
id: doc.get(FirestoreConstants.id),
name: doc.get(FirestoreConstants.name),
address: doc.get(FirestoreConstants.address),
postcode: doc.get(FirestoreConstants.postcode),
lat: doc.get(FirestoreConstants.lat),
long: doc.get(FirestoreConstants.long),
courierId: 'inpost',
);
selectedPickupPoint = PickupPointModel(
id: doc.get(FirestoreConstants.id),
name: doc.get(FirestoreConstants.name),
address: doc.get(FirestoreConstants.address),
postcode: doc.get(FirestoreConstants.postcode),
lat: doc.get(FirestoreConstants.lat),
long: doc.get(FirestoreConstants.long),
courierId: doc.data()?.containsKey('courierId') == true
? doc.get('courierId')
: 'inpost',
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/checkout_view_model.dart` around lines 443 - 451, The
selectedPickupPoint is being hydrated with a hardcoded courierId ('inpost')
which can misrepresent stored data; update the hydration in the code that builds
PickupPointModel (the selectedPickupPoint assignment) to read courierId from the
Firestore document (use doc.get(FirestoreConstants.courierId) or a safe default
if missing) so PickupPointModel.courierId reflects the stored value instead of
always 'inpost'.

Comment on lines +585 to +594
final Map<String, dynamic> deliveryDetails = deliveryChoice == 'pickup'
? {
"deliveryMethod": "pickup_point",
"courier": selectedPickupPoint?.courierId ?? 'unknown',
"pickupPointId": selectedPickupPoint?.id ?? 'unknown',
"pickupPointName": selectedPickupPoint?.name ?? 'unknown',
}
: {
"deliveryMethod": "ship_to_home",
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

'unknown' fallback values may reach the backend.

If selectedPickupPoint is null when deliveryChoice == 'pickup', the order payload will contain courier: 'unknown' and pickupPointId: 'unknown'. While the UI should prevent this, adding an explicit guard would catch edge cases and fail fast:

🛡️ Suggested defensive check
  Future<void> createOrder() async {
    _createOrderStatus = Status.loading;
    notifyListeners();

    if (basketItems.isEmpty) {
      _createOrderStatus = Status.failure('Your basket is empty');
      notifyListeners();
      return;
    }

+   if (deliveryChoice == 'pickup' && selectedPickupPoint == null) {
+     _createOrderStatus = Status.failure('Please select a pickup point');
+     notifyListeners();
+     return;
+   }
+
    final Map<String, dynamic> address = deliveryChoice == "pickup"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/checkout_view_model.dart` around lines 585 - 594, The
deliveryDetails construction uses fallback 'unknown' values when deliveryChoice
== 'pickup' but selectedPickupPoint can be null; add a defensive guard before
building deliveryDetails: check deliveryChoice == 'pickup' and if
selectedPickupPoint == null then fail fast (throw an exception, return an error,
or log and abort submission) so you never send courier: 'unknown' or
pickupPointId: 'unknown'; update the function that builds/returns
deliveryDetails (referenced by deliveryChoice and selectedPickupPoint) to
perform this validation and handle the error path appropriately.

if (inposts.isEmpty) {
return PickupPointsEmptyWidget();
}
} else if (status.type == StatusType.success || status.type == StatusType.uninitialized) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Treating uninitialized and success identically may cause confusing UX.

When status.type == StatusType.uninitialized, the UI renders the pickup content (courier list or points) before any fetch has occurred. This could display hardcoded mock data immediately, masking the fact that no real API call has been made.

Consider either:

  1. Showing a prompt to enter postcode first, or
  2. Only rendering content on StatusType.success
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/widgets/delivery_options.dart` at line 298, The branch
treating StatusType.uninitialized the same as StatusType.success causes mock
pickup content to render before a fetch; update the conditional in the widget
that checks status.type so it only treats StatusType.success as the "show
results" path (i.e., replace the combined check in the clause that currently
reads "status.type == StatusType.success || status.type ==
StatusType.uninitialized" with a single check for StatusType.success), and add
an explicit branch for StatusType.uninitialized that renders a
prompt/placeholder asking the user to enter a postcode (or otherwise indicates
no data fetched yet) so the UI does not display pickup lists/points prematurely.

Comment on lines +356 to +361
ListTile(
title: Text('${courier.name} Pick-up Points'),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
onTap: () {
model.setSelectedCourier(courier);
model.fetchNearestPickupPoints(postcodeController.text.trim());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, find the file and confirm its existence
find . -name "delivery_options.dart" -type f

Repository: Cherry-CIC/MVP

Length of output: 112


🏁 Script executed:

# Check the repository structure
ls -la

Repository: Cherry-CIC/MVP

Length of output: 1739


🏁 Script executed:

# Look for model/view model files related to delivery or checkout
find . -path "*/checkout/*" -name "*.dart" -type f | head -20

Repository: Cherry-CIC/MVP

Length of output: 1154


🏁 Script executed:

# Check the size of delivery_options.dart first
wc -l lib/features/checkout/widgets/delivery_options.dart

Repository: Cherry-CIC/MVP

Length of output: 114


🏁 Script executed:

# Read the relevant section around lines 356-361
sed -n '350,370p' lib/features/checkout/widgets/delivery_options.dart

Repository: Cherry-CIC/MVP

Length of output: 1265


🏁 Script executed:

# Check the checkout_view_model.dart to find the relevant methods and fields
wc -l lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 109


🏁 Script executed:

# Find fetchNearestPickupPoints method in the view model
grep -n "fetchNearestPickupPoints" lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 182


🏁 Script executed:

# Find nearestPickupPoints getter
grep -n "nearestPickupPoints" lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 265


🏁 Script executed:

# Find the _nearestInpost and _nearestPickupPoints fields
grep -n "_nearestInpost\|_nearestPickupPoints" lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 380


🏁 Script executed:

# Read the fetchNearestPickupPoints method implementation (lines around 374)
sed -n '374,410p' lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 1335


🏁 Script executed:

# Also check what's in _nearestPickupPoints initialization
sed -n '46,85p' lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 1114


🏁 Script executed:

# Check where nearestPickupPoints is used in the delivery_options.dart
grep -n "nearestPickupPoints" lib/features/checkout/widgets/delivery_options.dart

Repository: Cherry-CIC/MVP

Length of output: 130


🏁 Script executed:

# Also check if nearestInpost is used anywhere in delivery_options.dart
grep -n "nearestInpost\|model.nearestInpost" lib/features/checkout/widgets/delivery_options.dart

Repository: Cherry-CIC/MVP

Length of output: 40


🏁 Script executed:

# Check the rest of the nearestPickupPoints getter implementation
sed -n '84,92p' lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 423


🏁 Script executed:

# Let me check if _nearestInpost is used anywhere else in the codebase
rg "_nearestInpost" lib/features/checkout/

Repository: Cherry-CIC/MVP

Length of output: 401


🏁 Script executed:

# Check if there's any conversion or transfer from _nearestInpost to _nearestPickupPoints
rg "nearestInpost\|_nearestPickupPoints" lib/features/checkout/checkout_view_model.dart -B 2 -A 2

Repository: Cherry-CIC/MVP

Length of output: 40


🏁 Script executed:

# Check what PickupPointModel and InpostModel are
grep -n "class PickupPointModel\|class InpostModel" lib/features/checkout/ -r

Repository: Cherry-CIC/MVP

Length of output: 40


🏁 Script executed:

# Find model files in the checkout feature
find lib/features/checkout -name "*.dart" | xargs grep -l "class PickupPointModel\|class InpostModel"

Repository: Cherry-CIC/MVP

Length of output: 42


🏁 Script executed:

# Check the models directory
ls -la lib/features/checkout/models/

Repository: Cherry-CIC/MVP

Length of output: 309


🏁 Script executed:

# Let me check what happens around line 373 in delivery_options.dart where nearestPickupPoints is used
sed -n '365,385p' lib/features/checkout/widgets/delivery_options.dart

Repository: Cherry-CIC/MVP

Length of output: 1012


🏁 Script executed:

# Find where PickupPointModel and InpostModel are defined
find lib -name "*.dart" | xargs grep -l "class PickupPointModel"
find lib -name "*.dart" | xargs grep -l "class InpostModel"

Repository: Cherry-CIC/MVP

Length of output: 132


🏁 Script executed:

# Check the showLocker usage to understand the state flow
grep -n "showLocker" lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 238


🏁 Script executed:

# Check if there's any logic that uses nearestInpost in the widget
grep -n "showLocker\|nearestInpost\|nearestPickupPoints" lib/features/checkout/widgets/delivery_options.dart | head -20

Repository: Cherry-CIC/MVP

Length of output: 225


🏁 Script executed:

# Check the context around line 271 to understand the state flow
sed -n '265,290p' lib/features/checkout/widgets/delivery_options.dart

Repository: Cherry-CIC/MVP

Length of output: 1191


🏁 Script executed:

# Read the core models to understand the structure
cat lib/core/models/pickup_point_model.dart
cat lib/core/models/inpost_model.dart

Repository: Cherry-CIC/MVP

Length of output: 1368


🏁 Script executed:

# Let me verify that nearestInpost getter is not used anywhere in the UI
grep -r "nearestInpost" lib/features/checkout/widgets/

Repository: Cherry-CIC/MVP

Length of output: 40


🏁 Script executed:

# Also check if _parseInpostList does any conversion to PickupPointModel
grep -n "_parseInpostList" lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 165


🏁 Script executed:

# Read the _parseInpostList method to understand the data transformation
sed -n '420,500p' lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 2706


🏁 Script executed:

# Let me check the _parseInpostList method to see what it does
sed -n '659,723p' lib/features/checkout/checkout_view_model.dart

Repository: Cherry-CIC/MVP

Length of output: 1906


🏁 Script executed:

# Verify if there's any connection between nearestInpost and the UI by checking for any observers
grep -n "nearestInpost" lib/features/checkout/ -r

Repository: Cherry-CIC/MVP

Length of output: 415


Fetch result is disconnected from UI display.

When a courier is tapped, fetchNearestPickupPoints is called and populates _nearestInpost with API results. However, the UI reads from the hardcoded _nearestPickupPoints list (filtered by courier ID), so the fetched data is never displayed. The showLocker flag is set based on API success, but the pickup points shown always come from mock data.

Two separate data models exist: InpostModel for the API response and PickupPointModel for the hardcoded UI list. The nearestInpost getter is not used in any widget.

This appears intentional for the development phase, but the data flow must be connected before production use.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/checkout/widgets/delivery_options.dart` around lines 356 - 361,
The UI is still bound to the hardcoded _nearestPickupPoints instead of the API
result stored in _nearestInpost, so tapping a courier updates
model._nearestInpost via fetchNearestPickupPoints but the widgets never read it;
update the data flow so the ListTile tap path (setSelectedCourier,
fetchNearestPickupPoints) results are displayed by wiring the UI to the
model.nearestInpost (or merging _nearestInpost into the existing
PickupPointModel list) and ensure showLocker is used to choose which list to
render; specifically change the widgets that currently read _nearestPickupPoints
to prefer model.nearestInpost when non-empty (or after successful fetch), and
keep setSelectedCourier, fetchNearestPickupPoints, nearestInpost,
_nearestInpost, _nearestPickupPoints and showLocker consistent so the fetched
points replace or augment the mock list.

Copy link
Copy Markdown
Collaborator

@CherryCIC CherryCIC left a comment

Choose a reason for hiding this comment

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

I think this is now in good condition. The reviews are coming back generally positive, and all conflicts are resolved.

Thank you for your work @Z3DDIEZ

@Z3DDIEZ
Copy link
Copy Markdown
Author

Z3DDIEZ commented May 7, 2026

No worries @CherryCIC , happy to help!

@CherryCIC
Copy link
Copy Markdown
Collaborator

We're just waiting on a second approval

@JaseElder
Copy link
Copy Markdown
Contributor

Will have a look tonight...

Copy link
Copy Markdown
Contributor

@JaseElder JaseElder left a comment

Choose a reason for hiding this comment

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

There are some unresolved coderabbit comments that need looked at here.

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.

5 participants