The saved-trips search, then saved searches, then tabs
The trip planner’s saved-trips page: a search box, filter chips, a sort menu and a pager each add to one search as the user acts, and the list page runs it as SQL with numbered parameters. Each level starts from the previous level’s finished code, so you can begin at any of them.
Users can now save a search. The sidebar lists saved searches by a label that says what each one finds, and clicking one runs it. The label and the SQL must come from the same choices in the same order, and the team expects a third form soon (a link to share a search).
Today the sidebar shows “not written yet”. If the label is written from the saved record by hand, it and the SQL each read the record their own way, and the next field the search gains has to be added to both.
Reproduce labelSaved({ filters: [kind overnight, place Harbor], sort: "name", page: 2 }) should be “kind is overnight and place is Harbor, by name, page 2”. Today it is “not written yet”.
Acceptance criteria SearchLabel is a second builder with the same steps: each filter becomes “field is value”, joined by “ and ” (“all trips” when there are none), then “, by field” for an order and “, page n” for a page; a later sort or page replaces an earlier one. applySearch replays a saved search into any builder that takes the steps: every filter in order, then the sort if there is one, then the page if there is one. It must work with a builder it has never seen. runSaved and labelSaved both go through applySearch, so the SQL and the label always come from the same steps. TripSearch’s rules still hold: clause order, numbering, allowed fields, a page needs an order. Notes Cases print SQL and its parameters, a label, or the steps a builder received, “filter kind overnight; orderBy name; page 2”; a case’s results are joined by “ || ”. The label builds without checking anything: a saved search the SQL rejects still gets a label, and the list page shows the rejection when it runs. Keep the names and signatures of SearchSteps, SavedSearch, SearchLabel, applySearch, runSaved and labelSaved; the checker calls them, and replays saved searches into a builder of its own.