Problem/Motivation

The offer card belongs to the calendar. The yoyaku_slot_offer theme hook, its template, its preprocess and css/offer.css sit in yoyaku_calendar, and between them they carry what a booker is deciding on: the tariff name, the places it covers, what is left, the price, the quantity control, the constraints that hold it back, and the live region that answers a click.

Nothing about any of that is particular to a calendar. An offer is a thing somebody can take, and the page that happened to draw one first should not be the module that owns it.

There is a boundary cost, and it is the one that bites. yoyaku_booking_fee declares yoyaku and yoyaku_payment, not yoyaku_calendar, and implements preprocess_yoyaku_slot_offer on a theme hook the calendar owns. It is a hook name and not a class import, so nothing fatals: the mention that a fee is added simply never appears where no calendar is installed. That is the quiet half of #3616250: Declare every module whose classes a submodule names.

The pieces underneath are already shared, which is what makes the split look accidental rather than deliberate. The quantity control and the queue it posts through are yoyaku_presentation's, and the notice region the card prints is styled in yoyaku_presentation/css/stepper.css while the card that prints it lives in the calendar.

Proposed resolution

Move the card to yoyaku_presentation: the theme hook, its template, its preprocess and its stylesheet, behind a yoyaku_presentation/offer library that pulls the stepper in with it. yoyaku_presentation depends on yoyaku alone, and both the calendar and the placement picker already depend on it, so nothing gains a dependency it did not have. A site then overrides one template to restyle an offer, and yoyaku_booking_fee preprocesses a hook owned by a module it can declare.

The hook is renamed yoyaku_offer, because the card is about an offer and not about a slot. The card's element properties (offer_label, offer_places, offer_price, offer_price_note, offer_availability, offer_full, offer_limit) become presentation's surface, named and documented as one rather than being whatever the booking form happened to pass.

yoyaku_slot_booking stays in the calendar. It wraps the slot page and is about that page, not about an offer. The line it prints under the title gets a stylesheet of the page's own, attached to the form: that rule rides on the card's library today, so a slot with nothing on offer draws no card and leaves its own heading unstyled.

The decision this issue had to settle, and what it is

The seat picker builds its own block in the browser, with ysm-area class names styled in yoyaku_placement, carrying an area name, what is left, and a per-tariff row of label, price and quantity control. The question was whether the picker adopts the card's class names so one stylesheet dresses both, or the card's stylesheet is written so that two markups can carry it.

Neither. The picker keeps its markup and its dress, and the card moves as it stands.

The picker's blocks sit in a column of a few hundred pixels beside a plan, where they read as entries of the same list as the places picked above them. The card is a row across the width of a page, with the price given real weight. Nor are the two the same shape: a block in the panel carries one area's name over several tariff rows, where a card is one offer entire, so a shared vocabulary would have to invent a group concept that only one of the two surfaces has. Dressing the panel as cards would make it something else, and giving it the card's class names while overriding every rule in the card's stylesheet would say the two are one thing dressed twice.

What the two surfaces really share is the stepper, the queue and the notice, and all three are already named as such. So the class names on the card do not change with this move, and nothing a site has already styled stops being styled. The reasoning is recorded where a reader will next ask for it: beside the panel's own rules in the placement stylesheet, and in the shared-widgets documentation.

Remaining tasks

  • Review the merge request.

Pre-1.0, so this is a rename with no update path to keep: no shim, and the old library and hook names go in the same commit as the new ones.

Follow-up, not settled here

A charge added on top of a price reaches the card and not the picker's blocks, which carry a label and a price and nothing else. The same is true of the lines that say what is holding an offer back. Both travel to the browser as payload rather than through the card, so moving the card does not settle either of them. Filed as #3616969: Say on the plan, as the booking page does, that a charge is added to the price.

AI-Generated: Yes (Claude Code was used to help draft this issue summary and to write the code on the merge request. I reviewed the work, and the test it changes was confirmed to fail against the unfixed code and to pass with the change.)

Issue fork yoyaku-3616886

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mably created an issue. See original summary.

mably’s picture

Status: Active » Needs review
mably’s picture

Title: Move the offer card to yoyaku_presentation, where both booking surfaces can use it » Move the offer card to yoyaku_presentation, so a module adding to it does not depend on the calendar
mably’s picture

Issue summary: View changes

  • mably committed abde94f0 on 1.x
    task: #3616886 Move the offer card to yoyaku_presentation, so a module...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.