Skip to content

Initial implementation of the client-side vehicle library - #1273

Merged
JGreenlee merged 42 commits into
masterfrom
feat/vehicle-library
Sep 5, 2026
Merged

Initial implementation of the client-side vehicle library#1273
JGreenlee merged 42 commits into
masterfrom
feat/vehicle-library

Conversation

@shankari

Copy link
Copy Markdown
Contributor

No description provided.

@shankari

Copy link
Copy Markdown
Contributor Author

@JGreenlee this is a good checkpoint for you to sync and work in parallel.
At this point, the basic e2e flow should work except that I get a 400 error from bikeep while trying to unlock the dock.

  • Setup the card (works)
  • Setup, checkout, checkin buttons are all enabled/disabled correctly
  • Refresh button pulls the setup state and rental history, similar to the onActive callback
  • Current rental state is populated from the rental history so the server is the source of truth
  • there is a button to pull the current set of bikeep locations

Couple of high-level TODOs:

  1. This doesn't have the "ticking clock" effect that we had earlier. Is that important? How do we restore that/reconcile with the server?
  2. How do we handle simulation mode? (related to the first question)
  3. The current status check call is always the "heavyweight" one that goes all the way to the stripe servers. We need this when we are in the setup flow, but maybe we can switch to the lighter weight call that only looks at the version on our server when we are out of that flow.
Control buttons List of locations Rental history
simulator_screenshot_DEBBFC3B-5B46-45F7-804A-AEE29BB0737E Simulator Screenshot - emission - 2026-08-21 at 22 38 13 Simulator Screenshot - emission - 2026-08-21 at 22 39 56

@shankari

Copy link
Copy Markdown
Contributor Author

The modal dialog tests were consistently failing, so rewrote them to be consistent with the DateModal so that they could be tested the same way, and because @JGreenlee is going to make all this be pretty anyway. The functionality still works and now the tests work too.

return dialog checkout initial accessory question checkout dialog
Simulator Screenshot - emission - 2026-08-21 at 23 49 33 Simulator Screenshot - emission - 2026-08-21 at 23 49 25 Simulator Screenshot - emission - 2026-08-21 at 23 47 14

shankari added a commit that referenced this pull request Aug 22, 2026
The modals are now rewritten to be more compatible with existing modals (like
the DateModal) and to be testable.

Summary of what was done:
- Removed the redundant <Modal> wrapper from both modal components (Paper's
  Dialog handles its own portal overlay)
- Replaced Checkbox.Item in CheckoutControlModal with a Button toggle (Paper's
  AnimatedText isn't findable by getByText)
- Added per-test jest.mock('react-native-paper', ...) in both test files,
  stubbing Dialog and TextInput with simple renderers that don't require
  SafeAreaProvider or PaperProvider context

Screenshots at:
#1273 (comment)
@codecov

codecov Bot commented Aug 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 65.39197% with 181 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.73%. Comparing base (13cca0d) to head (4e77a14).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/js/library/LibraryTab.tsx 75.87% 55 Missing ⚠️
src/js/library/components/AvailableVehicles.tsx 46.93% 51 Missing and 1 partial ⚠️
src/js/library/components/QRScanner.tsx 40.54% 22 Missing ⚠️
src/js/library/components/LibraryDevPanel.tsx 10.52% 17 Missing ⚠️
src/js/App.tsx 0.00% 11 Missing ⚠️
src/js/library/components/ReturnFlow.tsx 78.94% 4 Missing and 4 partials ⚠️
src/js/Main.tsx 0.00% 6 Missing ⚠️
src/js/components/LeafletView.tsx 20.00% 4 Missing ⚠️
src/js/library/components/ActiveRental.tsx 80.00% 1 Missing and 1 partial ⚠️
src/js/library/components/CheckoutFlow.tsx 90.90% 2 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1273      +/-   ##
==========================================
+ Coverage   30.03%   33.73%   +3.69%     
==========================================
  Files         133      142       +9     
  Lines        4838     5351     +513     
  Branches     1170     1354     +184     
==========================================
+ Hits         1453     1805     +352     
- Misses       3375     3530     +155     
- Partials       10       16       +6     
Flag Coverage Δ
unit 33.73% <65.39%> (+3.69%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/js/AppContext.ts 100.00% <100.00%> (ø)
src/js/AppStatusModal.tsx 0.00% <ø> (ø)
src/js/appstatus/PermissionsControls.tsx 0.00% <ø> (ø)
src/js/control/CustomLabelSettingRow.tsx 0.00% <ø> (ø)
src/js/control/FeedbackModal.tsx 0.00% <ø> (ø)
src/js/control/ProfileSettings.tsx 0.00% <ø> (ø)
src/js/control/ReminderTimeSettingRow.tsx 0.00% <ø> (ø)
src/js/control/devzone/DeveloperZone.tsx 0.00% <ø> (ø)
src/js/control/devzone/EditSyncConfigModal.tsx 0.00% <ø> (ø)
src/js/customEventHandler.ts 100.00% <ø> (ø)
... and 23 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@shankari
shankari force-pushed the feat/vehicle-library branch 2 times, most recently from 9bb24e9 to e768900 Compare August 22, 2026 07:07
@JGreenlee

Copy link
Copy Markdown
Member

I tested this e2e on Friday with e-mission/e-mission-server#1099 and find that payment setup -> checkout and unlock -> return and lock flow works well.

I have rebased this branch to incorporate the changes from #1169, which will make it easier to incorporate the UI I have been building into this PR.
Awaiting checks before merging #1169 and will then push the rebase of this branch

JGreenlee pushed a commit that referenced this pull request Aug 31, 2026
The modals are now rewritten to be more compatible with existing modals (like
the DateModal) and to be testable.

Summary of what was done:
- Removed the redundant <Modal> wrapper from both modal components (Paper's
  Dialog handles its own portal overlay)
- Replaced Checkbox.Item in CheckoutControlModal with a Button toggle (Paper's
  AnimatedText isn't findable by getByText)
- Added per-test jest.mock('react-native-paper', ...) in both test files,
  stubbing Dialog and TextInput with simple renderers that don't require
  SafeAreaProvider or PaperProvider context

Screenshots at:
#1273 (comment)
@JGreenlee
JGreenlee force-pushed the feat/vehicle-library branch from e768900 to 440592b Compare August 31, 2026 18:16
JGreenlee pushed a commit that referenced this pull request Aug 31, 2026
The modals are now rewritten to be more compatible with existing modals (like
the DateModal) and to be testable.

Summary of what was done:
- Removed the redundant <Modal> wrapper from both modal components (Paper's
  Dialog handles its own portal overlay)
- Replaced Checkbox.Item in CheckoutControlModal with a Button toggle (Paper's
  AnimatedText isn't findable by getByText)
- Added per-test jest.mock('react-native-paper', ...) in both test files,
  stubbing Dialog and TextInput with simple renderers that don't require
  SafeAreaProvider or PaperProvider context

Screenshots at:
#1273 (comment)
@JGreenlee
JGreenlee force-pushed the feat/vehicle-library branch 2 times, most recently from 5e77bec to 44792f7 Compare September 4, 2026 16:36
- Setup using checkout session with mode `setup`
    - Note that setting the success URL to an app URL (e.g. `emission://...`) works!
- Deposit + refund flow ($200 - $150)
- Direct payment flow ($50)

All code is clean and does not have any secrets embedded in it.
- checkout
    - ask people if they want accessories
    - place a hold
    - scan/enter bike ID
    - map it to a dock ID
    - unlock the dock
    - store the bike_id as the current one

- return
    - capture the payment
    - scan/enter dock ID
    - lock the dock
    - map dock to bike for future unlocks

- simulations:
    - setup is in-memory
    - mapping between dock and bike is hardcoded
    - current bike is in-memory
    - enter supported in addition to scan since simulator cannot scan
Add a "simulation mode" in which we can force time to pass more quickly.
This will allow us to experiment with different payment scenarios.

This is still fairly buggy/incomplete:
1. I had to bump up the deposit from 200/250 to 400/450 because otherwise,
attempting to capture $380 after a two week rental fails, and the error
reporting does not appear to work. It looks like the popup to enter the dock ID
just hangs.
2. All information related to the stripe integration is stored only in memory and is reset on every launch.
3. We are making direct calls to stripe instead of going through a proxy. If we
do have to go through proxies for both the bikeep integration and the stripe
integration, maybe we should hook them up on the server instead.
Which is the max payment of $380, consistent with or without accessories
Switch the setup functionality to work through the server instead of direct API calls.
To support this, we plumbed through some new server call wrappers, and a new custom event.

What currently works:
- Launch app
- Click on setup
- Fill out information from a hosted page at Stripe
- Control returns to app (via a prompt) and the checkout button is enabled.

Note that this is not complete because every time the app is launched, it is in
the `setupComplete = false` state. I tried to fix this by checking for the
current state while resuming the app, but haven't had time to debug it yet. And
going back to setup every time is easier for my testing anyway.

Related server commit: e-mission/e-mission-server#1099
This still needs significant refactoring/simplification, but checking it in as
a working PoC for now.

Corresponding server change is:
e-mission/e-mission-server@fea367b
- Check the status on every launch, so we can handle the case in which the user
    returns to the app in some other way
- Ensure that if the card has already been setup, we know that, and don't have
  to re-enter it over and over
- Include a TODO performance optimization
- Fix the unit tests to match

Corresponds to server changes:
e-mission/e-mission-server@4a769cd
Since we are not communicating with stripe directly any more, and are proxying
calls through the server, stripeCheckout doesn't really make sense any more.
And some of the functions are now completely unrelated to stripe (e.g. getRentalHistory).
Add simple wrappers for the server endpoints
Define types for the expected return values and use them
Change existing methods to use the new wrappers

Next step: remove all direct calls, and switch the UI to use the new wrappers directly
- Remove all references to the direct stripe integration
- Remove all supporting functions
- Remove all related data types
- Swap the old direct calls with the new wrapper calls in the library tab
- Add code to read the current rental history when the library tab becomes active

Next step: Use the most recent active rental from the server for the display
instead of locally stored fields
Similar to the dashboard, refreshes the same state as when the tab becomes active
shankari and others added 27 commits September 4, 2026 13:04
…sible

Adjust the components so that the rental history is actually visible
Populated fake rental data for the user and verified that it was displayed in the UI
(see PR for screenshots)
Instead of storing another copy of the current rental values locally,
read it from the rental history, since the server is the source of truth.

TODO:
1. This doesn't have the "ticking clock" effect that we had earlier. Is that
important? How do we restore that/reconcile with the server?
2. How do we handle simulation mode? (related to the first question)
Without that, none of the checkin/checkout tests will pass since the buttons
will always be disabled.
The modals are now rewritten to be more compatible with existing modals (like
the DateModal) and to be testable.

Summary of what was done:
- Removed the redundant <Modal> wrapper from both modal components (Paper's
  Dialog handles its own portal overlay)
- Replaced Checkbox.Item in CheckoutControlModal with a Button toggle (Paper's
  AnimatedText isn't findable by getByText)
- Added per-test jest.mock('react-native-paper', ...) in both test files,
  stubbing Dialog and TextInput with simple renderers that don't require
  SafeAreaProvider or PaperProvider context

Screenshots at:
#1273 (comment)
Add components for browsing available vehicles, displaying the active
rental, checking out and returning vehicles, and scanning QR codes.
This will replace the "bare-bones" UI that was being used to demo before
Replace the bare-bones vehicle library UI with the new componentized checkout, return, rental, and vehicle-list flows.

Remove the obsolete modal components and update the LibraryTab and app navigation to use the new UI structure.

Also implements the configurable fee_expression instead of the hardcoded computeFee
When the admin scans an unitialized bike they have a vehicle rental with "initializing" as the state. We need the UI to recognize this - and for the most part, treat it like an active rental - but there will be no payment, so we need to change some of the strings to not make it too confusing to them.

Also refined strings that were misleading; i.e. "Open Stripe for ${{amount}} Deposit", which was misleading because by that point Stripe has already been set up and ready to charge; there is nothing opened. "Check Out (${{amount}} hold)" reflects it better
Since e5284b1 the server comm mock now actually tries to call the server for getUserPersonalData/postUserPersonalData (works great in browser dev mode, not under Jest) and returns early without invoking either callback when there's no opcode, which affected the whole suite. mocking empty response fixes it
@JGreenlee
JGreenlee force-pushed the feat/vehicle-library branch from 44792f7 to 4e77a14 Compare September 4, 2026 17:05
@JGreenlee
JGreenlee merged commit 1a08305 into master Sep 5, 2026
5 checks passed
@github-project-automation github-project-automation Bot moved this to Tasks completed in OpenPATH Tasks Overview Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Tasks completed

Development

Successfully merging this pull request may close these issues.

2 participants