Skip to content

Commit e81580d

Browse files
committed
feat: show chosen payment option in action card
1 parent afd5de7 commit e81580d

3 files changed

Lines changed: 35 additions & 1 deletion

File tree

ai-server/src/mastra/tools/book-flight.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,14 @@ const flightSchema = z.object({
3838
// Shape mirrors Mastra's tool-result convention (`result: string`) with
3939
// additive domain fields (`flight`, `code`), so our own returns and Mastra's
4040
// built-in decline string normalize into the same client type.
41+
const paymentMethodSchema = z.enum(['creditCard', 'miles']);
42+
4143
const resultSchema = z.union([
4244
z.object({
4345
ok: z.literal(true),
4446
result: z.string(),
4547
flight: flightSchema,
48+
paymentMethod: paymentMethodSchema.optional(),
4649
}),
4750
z.object({
4851
ok: z.literal(false),
@@ -158,6 +161,7 @@ export const bookFlightTool = createTool({
158161
ok: true as const,
159162
result: `Booked flight ${flightId} from ${flight.from} to ${flight.to} on ${formatFlightDate(flight.date)}${paymentSuffix}.`,
160163
flight,
164+
paymentMethod: selection,
161165
};
162166
},
163167
});

src/app/domains/ticketing/ai/widgets/book-flight-action-card.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
BookingClient,
1717
type FlightMutationFlight,
1818
type FlightMutationResult,
19+
type FlightPaymentMethod,
1920
} from '../../data/flight-mutation-client';
2021
import {
2122
getActionStatusLabel,
@@ -25,6 +26,11 @@ import {
2526
toLoadFailedResult,
2627
} from './card-utils';
2728

29+
const PAYMENT_METHOD_LABELS: Record<FlightPaymentMethod, string> = {
30+
creditCard: 'Credit card',
31+
miles: 'Bonus miles',
32+
};
33+
2834
interface BookFlightInput {
2935
flightId: number;
3036
}
@@ -48,6 +54,10 @@ type BookFlightActionData = AgUiActionData<
4854
4955
<p class="status-line">Status: {{ statusLabel() }}</p>
5056
57+
@if (paymentMethodLabel(); as paymentLabel) {
58+
<p class="payment-line">Payment: {{ paymentLabel }}</p>
59+
}
60+
5161
@if (showUndo()) {
5262
<p>
5363
<button class="btn btn-default" type="button" (click)="undo()">
@@ -83,6 +93,10 @@ type BookFlightActionData = AgUiActionData<
8393
color: #4e5b78;
8494
}
8595
96+
.payment-line {
97+
color: #4e5b78;
98+
}
99+
86100
p {
87101
margin-top: 0;
88102
margin-bottom: 0;
@@ -139,6 +153,19 @@ export class BookFlightActionCard implements AgUiActionCard<BookFlightActionData
139153
),
140154
);
141155

156+
protected readonly paymentMethodLabel = computed(() => {
157+
if (this.undoResult()) {
158+
return null;
159+
}
160+
161+
const result = this.result();
162+
if (!result?.ok || !result.paymentMethod) {
163+
return null;
164+
}
165+
166+
return PAYMENT_METHOD_LABELS[result.paymentMethod];
167+
});
168+
142169
protected async undo(): Promise<void> {
143170
this.undoPending.set(true);
144171

src/app/domains/ticketing/data/flight-mutation-client.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@ export type FlightMutationFailureCode =
2121
| 'LOAD_FAILED'
2222
| 'USER_CANCELLED';
2323

24+
export type FlightPaymentMethod = 'creditCard' | 'miles';
25+
2426
// Shape aligned with Mastra's tool-result convention (`result: string`) so
2527
// both our own tool returns and Mastra's built-in decline ("Tool call was not
2628
// approved by the user") map onto the same type. Extra fields (`flight`,
27-
// `code`) are additive domain data.
29+
// `code`, `paymentMethod`) are additive domain data.
2830
export type FlightMutationResult =
2931
| {
3032
ok: true;
3133
result: string;
3234
flight: FlightMutationFlight;
35+
paymentMethod?: FlightPaymentMethod;
3336
}
3437
| {
3538
ok: false;

0 commit comments

Comments
 (0)