@tribe-nest/forge 3.53.0 → 3.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/src/contexts/AppAuthContext.tsx +3 -2
  3. package/src/contexts/AudioPlayerContext.tsx +3 -2
  4. package/src/contexts/CartContext.tsx +3 -2
  5. package/src/contexts/PublicAuthContext.tsx +3 -2
  6. package/src/data/queries/useEvents.ts +14 -0
  7. package/src/data/queries/useMyTickets.ts +49 -0
  8. package/src/data/queries/usePaymentFlow.ts +8 -0
  9. package/src/i18n/de.json +42 -1
  10. package/src/i18n/en.json +42 -1
  11. package/src/i18n/index.ts +3 -2
  12. package/src/index.ts +22 -0
  13. package/src/provider/ForgeAppProvider.tsx +8 -1
  14. package/src/provider/ForgeProvider.tsx +3 -2
  15. package/src/provider/SiteConfigProvider.tsx +3 -2
  16. package/src/runtime/RemotePage.tsx +110 -0
  17. package/src/runtime/hostRuntime.ts +84 -0
  18. package/src/runtime/pages.spec.ts +41 -0
  19. package/src/runtime/pages.ts +183 -0
  20. package/src/runtime/pagesClient.ts +127 -0
  21. package/src/runtime/registry.spec.ts +45 -0
  22. package/src/runtime/registry.ts +102 -0
  23. package/src/server/jobs.ts +4 -1
  24. package/src/server/platformEvents.generated.ts +92 -0
  25. package/src/types/models.ts +58 -0
  26. package/src/ui/headless/event/_tests/ticketApproval.spec.ts +137 -0
  27. package/src/ui/headless/event/_tests/useEventCheckoutApproval.spec.tsx +250 -0
  28. package/src/ui/headless/event/ticketApproval.ts +109 -0
  29. package/src/ui/headless/event/useEventCheckout.ts +74 -4
  30. package/src/ui/headless/index.ts +11 -0
  31. package/src/ui/index.ts +18 -0
  32. package/src/ui/payment/ForgePaymentProvider.tsx +15 -0
  33. package/src/ui/payment/ForgeStripePayment.tsx +37 -3
  34. package/src/ui/payment/_tests/stripeConfirmOutcome.spec.ts +61 -0
  35. package/src/ui/payment/stripeConfirmOutcome.ts +50 -0
  36. package/src/ui/shell/TribeNestApp.tsx +6 -0
  37. package/src/ui/styled/AccountDashboard.tsx +79 -13
  38. package/src/ui/styled/DocumentSigningPage.tsx +516 -0
  39. package/src/ui/styled/EventConfirmation.tsx +106 -9
  40. package/src/ui/styled/EventTickets.tsx +107 -13
  41. package/src/ui/styled/ReviewRequestPage.tsx +214 -0
  42. package/src/ui/styled/forge-utilities.css +310 -0
  43. package/src/ui/theme/ForgeThemeProvider.tsx +3 -2
  44. package/src/utils/_tests/ticketOrderOutcome.spec.ts +82 -0
  45. package/src/utils/ticketOrderOutcome.ts +57 -1
@@ -51,15 +51,40 @@ export type TicketOrderOutcome =
51
51
  | "paid"
52
52
  /** Was paid, money has gone back, the ticket no longer admits entry. */
53
53
  | "refunded"
54
- /** Never paid — abandoned checkout or a failed payment. */
54
+ /**
55
+ * A ticket REQUEST the organiser has not decided yet (curated access,
56
+ * feature 3). The charge is committed but not taken, the seat is held, and
57
+ * no pass exists. Covers `pending_approval` and the transient `approved`,
58
+ * because from the fan's side "approved, settling" is still "waiting".
59
+ */
60
+ | "awaiting_approval"
61
+ /** The organiser said no. Nothing was charged and the hold was released. */
62
+ | "declined"
63
+ /** Never paid: abandoned checkout, a failed payment, or a request that lapsed or could not settle. */
55
64
  | "not_completed";
56
65
 
66
+ /**
67
+ * Why a request ended without a sale, when it did. Picks the copy on a
68
+ * `not_completed` or `declined` outcome; `null` for an ordinary abandoned or
69
+ * declined-card order, whose copy is unchanged.
70
+ */
71
+ export type TicketRequestFailureKind = "declined" | "expired" | "payment_failed";
72
+
57
73
  /** The only fields of a ticket order this decision reads. */
58
74
  export interface TicketOrderOutcomeInput {
59
75
  status: OrderStatus | string;
60
76
  /** Bigint column — arrives over JSON as a string. */
61
77
  refundedAmountCents?: number | string | null;
62
78
  refundState?: string | null;
79
+ /**
80
+ * Set when this order was a ticket request that ended without a sale:
81
+ * `"expired"` on a `cancelled` row whose window lapsed undecided, the
82
+ * provider's reason on a `payment_failed` row that was approved but could
83
+ * not settle. Absent on an ordinary sale and on an older API build.
84
+ */
85
+ approvalFailureReason?: string | null;
86
+ /** Stamped when the request was lodged. A second signal that a `payment_failed` row was a request. */
87
+ approvalRequestedAt?: string | null;
63
88
  }
64
89
 
65
90
  /**
@@ -77,6 +102,9 @@ const PAID_STATES = new Set<string>([
77
102
  OrderStatus.Processed,
78
103
  ]);
79
104
 
105
+ /** A request the organiser has not finished deciding. `approved` is transient: settlement is in flight. */
106
+ const AWAITING_APPROVAL_STATES = new Set<string>([OrderStatus.PendingApproval, OrderStatus.Approved]);
107
+
80
108
  /** Has any money gone back on this order? */
81
109
  export function isTicketOrderRefunded(order: TicketOrderOutcomeInput): boolean {
82
110
  const cents = Number(order.refundedAmountCents ?? 0);
@@ -97,10 +125,38 @@ export function isTicketOrderRefunded(order: TicketOrderOutcomeInput): boolean {
97
125
  */
98
126
  export function getTicketOrderOutcome(order: TicketOrderOutcomeInput): TicketOrderOutcome {
99
127
  if (PAID_STATES.has(order.status)) return "paid";
128
+ // Before the refund test: nothing has been captured on a request, so the
129
+ // refund columns are at their defaults and cannot say anything about it.
130
+ if (AWAITING_APPROVAL_STATES.has(order.status)) return "awaiting_approval";
131
+ if (order.status === OrderStatus.Declined) return "declined";
100
132
  if (isTicketOrderRefunded(order)) return "refunded";
101
133
  return "not_completed";
102
134
  }
103
135
 
136
+ /**
137
+ * Which way a ticket request ended, for an order that is `declined` or
138
+ * `not_completed`. `null` when the order was never a request, or is still one
139
+ * (`awaiting_approval`), or succeeded (`paid`), so an ordinary abandoned
140
+ * checkout keeps its ordinary copy.
141
+ *
142
+ * declined the organiser said no
143
+ * expired the window lapsed with no decision; the sweep cancelled it
144
+ * payment_failed approved, but the deferred charge could not be settled
145
+ *
146
+ * `payment_failed` is recognised by `approvalFailureReason` OR
147
+ * `approvalRequestedAt`: the contract sets the reason on that row, and the
148
+ * requested-at stamp is a belt-and-braces signal for a provider that reports
149
+ * no reason. An ordinary declined card carries neither.
150
+ */
151
+ export function ticketRequestFailureKind(order: TicketOrderOutcomeInput): TicketRequestFailureKind | null {
152
+ if (order.status === OrderStatus.Declined) return "declined";
153
+ if (order.status === OrderStatus.Cancelled && order.approvalFailureReason === "expired") return "expired";
154
+ if (order.status === OrderStatus.PaymentFailed && (order.approvalFailureReason || order.approvalRequestedAt)) {
155
+ return "payment_failed";
156
+ }
157
+ return null;
158
+ }
159
+
104
160
  /**
105
161
  * The refunded copy, shared verbatim by both rendering surfaces (the Forge
106
162
  * `EventConfirmation` block and the client app's `/events/:id/finalise` page)