Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@
},
{
"includes": [
"src/shared/db/migrations/schema.ts",
"src/ui/templates/public/reservations.tsx"
"src/shared/db/migrations/schema.ts"
],
"linter": {
"rules": {
Expand Down
2 changes: 1 addition & 1 deletion src/features/public/qr-book.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { qrBookErrorPage } from "#templates/public/errors.tsx";
import type {
BookingPrefill,
TicketPrefill,
} from "#templates/public/reservations.tsx";
} from "#templates/public/reservations/types.ts";
import { getTicketContext, runCheckoutFlow } from "./ticket-payment.ts";
import { handleTicket } from "./ticket-submit.ts";

Expand Down
2 changes: 1 addition & 1 deletion src/features/public/ticket-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { mergeListingFields } from "#shared/listing-fields.ts";
import type { ListingFields } from "#shared/types.ts";
import { parseNonNegativeInt } from "#shared/validation/number.ts";
import { extractContact } from "#templates/fields/ticket.ts";
import { ticketPage } from "#templates/public/reservations.tsx";
import { ticketPage } from "#templates/public/reservations/ticket-page.tsx";
import type { ListingQty, TicketCtx } from "./types.ts";

/** Parse and validate a quantity value from a raw string, capping at max */
Expand Down
2 changes: 1 addition & 1 deletion src/features/public/ticket-submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
import type {
BookingPrefill,
TicketPrefill,
} from "#templates/public/reservations.tsx";
} from "#templates/public/reservations/types.ts";
import {
applyBookingPageParentSoldOut,
childCapacityInfo,
Expand Down
7 changes: 2 additions & 5 deletions src/features/public/ticket-submit/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
customPriceFieldName,
packageQuantityFieldName,
quantityFieldName,
standaloneListingIds,
} from "#shared/booking/tree.ts";
import { getOrCreateStringIds } from "#shared/db/questions/strings.ts";
import type { FormParams } from "#shared/form-data.ts";
Expand Down Expand Up @@ -222,11 +223,7 @@ export const resolvePageQuantities = (
): { nodeQuantities: Map<string, number>; quantities: Map<number, number> } => {
// Listings with a standalone node keep their own quantity_<id> input — every
// non-member, plus any member the cart also added by its own slug.
const standaloneIds = new Set(
tree.nodes
.filter((node) => node.quantityRule.kind === "BUYER_CHOICE")
.map((node) => node.listingId),
);
const standaloneIds = standaloneListingIds(tree);
const standaloneQuantities = parseQuantities(
form,
ctx.listings.filter((info) => standaloneIds.has(info.listing.id)),
Expand Down
2 changes: 1 addition & 1 deletion src/features/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
ItemImageProjection,
ListingWithCount,
} from "#shared/types.ts";
import type { BookingPrefill } from "#templates/public/reservations.tsx";
import type { BookingPrefill } from "#templates/public/reservations/types.ts";

/** Parent listing id → its bookable-child candidates, each hydrated to a
* {@link TicketListing} so availability (isSoldOut/isClosed/maxPurchasable) is
Expand Down
16 changes: 16 additions & 0 deletions src/shared/booking/package-cap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ export const packageLimitInfo = (
...groupCapacityInfo(groupRemainingByGroupId, groupIdsByListingId),
});

/** Each page package's whole-bundle limit, keyed by group id. Builds the
* page-level {@link PackageLimitInfo} once and maps each package over
* {@link pagePackageBundleLimit}, so callers stop re-stating the four
* limit-info arguments per call site. */
export const pageBundleLimits = (
tree: BookingTree,
packages: readonly TreePackage[],
page: PackageLimitInfo,
): Map<number, number> =>
new Map(
packages.map((pkg) => [
pkg.groupId,
pagePackageBundleLimit(tree, pkg, page),
]),
);

export const childCanBeBooked: (child: TicketListing) => boolean =
childPassesAllChecks([childActive, childOpen, childInStock]);

Expand Down
11 changes: 11 additions & 0 deletions src/shared/booking/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,14 @@ export const nodePriceFieldName = (node: BookingNode): string | null => {
? childPriceFieldName(node.edgeRef.parentId, node.listingId)
: customPriceFieldName(node.listingId);
};

/** The listing ids that carry a standalone `BUYER_CHOICE` node — i.e. the rows
* with their own quantity selector (every non-member, plus any member the cart
* also added by its own slug). The render path and the submit parser both derive
* this from the same tree so the two can't drift. */
export const standaloneListingIds = (tree: BookingTree): Set<number> =>
new Set(
tree.nodes
.filter((node) => node.quantityRule.kind === "BUYER_CHOICE")
.map((node) => node.listingId),
);
Loading