Bug 41129 - Migrate place_booking.js to a Vue island.
Summary: Migrate place_booking.js to a Vue island.
Status: NEW
Alias: None
Product: Koha
Classification: Unclassified
Component: Circulation (show other bugs)
Version: Main
Hardware: All All
: P5 - low enhancement
Assignee: Bugs List
QA Contact: Testopia
URL:
Keywords:
Depends on: 29002
Blocks:
  Show dependency treegraph
 
Reported: 2025-10-29 10:02 UTC by Paul Derscheid
Modified: 2025-10-29 14:35 UTC (History)
2 users (show)

See Also:
GIT URL:
Initiative type: ---
Sponsorship status: ---
Crowdfunding goal: 0
Patch complexity: Large patch
Documentation contact:
Documentation submission:
Text to go in the release notes:
Version(s) released in:
Circulation function: Bookings


Attachments
Bug 41129: [DO NOT PUSH] Add BookingModal.vue, remove place_booking.{inc,js} (404.09 KB, patch)
2025-10-29 11:13 UTC, Paul Derscheid
Details | Diff | Splinter Review
Bug 41129: Use Bootstrap 5 Modal API for booking modal (16.09 KB, patch)
2025-10-29 14:35 UTC, Paul Derscheid
Details | Diff | Splinter Review

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Derscheid 2025-10-29 10:02:42 UTC
Since the bookings functionality requires a significant amount of reactivity due to many interdependent inputs to achieve a good UX, this bug is intended to deprecate place_booking.js in favor of a Vue island that makes this much easier.

The goal here is to have a Vue based component that is used for the Staff Interface as well as the OPAC to avoid duplication and diverging implementations and also makes it easier to keep track of problems that then don't need to be fixed in two places.
Comment 1 Paul Derscheid 2025-10-29 11:13:33 UTC
Created attachment 188546 [details] [review]
Bug 41129: [DO NOT PUSH] Add BookingModal.vue, remove place_booking.{inc,js}

- Migration to Vue
- Pinia store integration
- Flatpickr calendar integration with constraint highlighting
- Multi-step booking form with validation
- Availability checking
- API adapter pattern (prep for full APIClient migration)

Technical notes:
The booking adapters currently use fetch() directly but have
been structured to facilitate migration to APIClient pattern.
Full APIClient migration requires:
- BiblioAPIClient for bookable items/pickup locations
- CheckoutAPIClient for checkout queries
- CirculationRulesAPIClient for rules endpoint
- PatronAPIClient.search() method enhancement

This work should be completed as a team effort to ensure
consistency across the codebase.

Test plan:

STAFF INTERFACE - Creating Bookings

Preparation:
- Run yarn js:build to emit the bundles

1. Navigate to a biblio detail page with bookable items
2. Click "Place booking" button
3. Observe the Vue booking modal opens

Step 1 - Patron Selection:
4. Type patron name/cardnumber in search field
5. Verify typeahead search returns results
6. Select a patron
7. Verify patron is selected and displays correctly

Step 2 - Booking Details:
8. Verify item type dropdown is populated
9. Select an item type
10. Verify pickup location dropdown is populated
11. Select a pickup location
12. If multiple bookable items exist, verify item dropdown appears
13. Select specific item (if applicable)

Step 3 - Booking Period:
14. Verify flatpickr calendar opens
15. Verify calendar shows existing bookings, checkouts,
    and available dates
16. Select a date range
17. Verify date range validation works
18. Verify lead period/trail period restrictions are enforced
19. Verify maximum booking period is enforced
20. Verify constraint highlighting updates correctly when changing
    item type, specific item, or pickup location

Validation Testing:
21. Try to submit without patron - verify error message
22. Try to submit without item type - verify error message
23. Try to submit without pickup location - verify error message
24. Try to submit without date range - verify error message
25. Try to select dates outside allowed range - verify validation

Capacity Testing:
26. For item type with limited bookable items, verify capacity warnings
27. Verify zero-capacity items show appropriate message

Submitting Bookings:
28. Complete all required fields
29. Click "Place booking"
30. Verify booking is created successfully
31. Verify modal closes
32. Verify booking appears in bookings list

STAFF INTERFACE - Editing Bookings

33. Click "Edit" on an existing booking
34. Verify modal opens with pre-filled data (patron, item type,
    pickup location, date range)
35. Modify the date range
36. Click "Update booking"
37. Verify changes are saved
38. Verify updated booking reflects changes

Calendar Navigation:
39. In date picker, navigate between months
40. Verify highlighting persists across navigation
41. Verify availability data loads correctly for new months

Error Handling:
42. Disconnect network
43. Try to create a booking
44. Verify appropriate error message displays
45. Restore network and verify subsequent booking attempts work

Store State Management:
46. Open booking modal and fill in some fields but don't submit
47. Close modal and re-open it
48. Verify modal state is reset (no data persists inappropriately)

Browser Console:
49. Throughout all tests, verify no JavaScript errors in console
50. Verify no warnings about deprecated code

Build Process:
51. Run yarn js:build{,:prod}
52. Verify build completes without errors
53. Verify dist files are generated correctly

Additional Regression Testing:
54. Test with various system preferences configurations
55. Test with multiple bookable items per biblio
56. Test with various circulation rules configurations
57. Test with different patron categories
58. Test booking constraints at item level vs itemtype level
Comment 2 Paul Derscheid 2025-10-29 11:52:07 UTC
Side note: there's some blocks lingering that mimic bootstrap functionality that was missing in 22.11 (where this was ported back to main from). I will remove that next.
Comment 3 Paul Derscheid 2025-10-29 14:35:48 UTC
Created attachment 188551 [details] [review]
Bug 41129: Use Bootstrap 5 Modal API for booking modal

- Use Bootstrap Modal API for show/hide/dispose lifecycle
- Replace custom modal classes with Bootstrap native classes
- Remove custom backdrop CSS
- Remove modal-scroll.mjs polyfill
- Unify two watchers on props.open into single watcher
- Add focus management to prevent aria-hidden warnings