393 lines
12 KiB
TypeScript
393 lines
12 KiB
TypeScript
export interface MockPassenger {
|
|
id: string;
|
|
passengerName: string;
|
|
pnr: string;
|
|
passengerType: string; // e.g. "VIP Adult", "Adult", "High Value", "Child", "Infant"
|
|
nationality: string; // e.g. "German", "British", "American", "Japanese", "French"
|
|
loyaltyTier: string; // e.g. "Platinum", "Gold", "Silver", "Bronze", "Regular"
|
|
specialAssistance: string; // e.g. "Wheelchair (WCHR)", "None", "Dietary Meal", "Medical"
|
|
originalCabin: string; // e.g. "First Class", "Business Class", "Premium Economy", "Economy"
|
|
actualCabin: string; // e.g. "Business Class", "Economy", "First Class" (assigned cabin after disruption)
|
|
cabinClass?: string; // Legacy fallback/alias
|
|
isHighValue?: boolean;
|
|
seatNumber?: string;
|
|
ticketNumber?: string;
|
|
}
|
|
|
|
export interface MockDisruption {
|
|
flightNumber: string;
|
|
date: string; // YYYY-MM-DD
|
|
origin: string; // IATA code
|
|
destination: string; // IATA code
|
|
category: string; // e.g. "flight_ops", "weather", "travel_exp"
|
|
scenario: string; // e.g. "delayed_flight", "cancelled_flight", "missed_connection"
|
|
jurisdiction: string; // e.g. "EU261", "US_DOT", "UK261"
|
|
delayDuration: number; // in minutes
|
|
status: string; // e.g. "Delayed", "Cancelled", "Diverted"
|
|
description?: string;
|
|
passengers: MockPassenger[];
|
|
}
|
|
|
|
export const MOCK_DISRUPTIONS: Record<string, MockDisruption> = {
|
|
B7687YT: {
|
|
flightNumber: 'B7687YT',
|
|
date: '2026-08-14',
|
|
origin: 'FRA',
|
|
destination: 'JFK',
|
|
category: 'flight_ops',
|
|
scenario: 'delayed_flight',
|
|
jurisdiction: 'EU261',
|
|
delayDuration: 240,
|
|
status: 'Delayed',
|
|
description: 'Technical engine maintenance delay at Frankfurt Airport.',
|
|
passengers: [
|
|
{
|
|
id: 'p-101',
|
|
passengerName: 'John Doe',
|
|
pnr: 'FT7687T9I',
|
|
passengerType: 'VIP Adult',
|
|
nationality: 'German',
|
|
loyaltyTier: 'Platinum',
|
|
specialAssistance: 'Wheelchair (WCHR)',
|
|
originalCabin: 'First Class',
|
|
actualCabin: 'Business Class', // Downgraded during disruption
|
|
cabinClass: 'First Class',
|
|
isHighValue: true,
|
|
seatNumber: '4A',
|
|
ticketNumber: '0162394810239',
|
|
},
|
|
{
|
|
id: 'p-102',
|
|
passengerName: 'Sarah Jenkins',
|
|
pnr: 'SJ98231FA',
|
|
passengerType: 'High Value Adult',
|
|
nationality: 'British',
|
|
loyaltyTier: 'Gold',
|
|
specialAssistance: 'None',
|
|
originalCabin: 'First Class',
|
|
actualCabin: 'First Class',
|
|
cabinClass: 'First Class',
|
|
isHighValue: true,
|
|
seatNumber: '2F',
|
|
ticketNumber: '0162394810240',
|
|
},
|
|
{
|
|
id: 'p-103',
|
|
passengerName: 'Michael Chen',
|
|
pnr: 'MC441298X',
|
|
passengerType: 'Adult',
|
|
nationality: 'American',
|
|
loyaltyTier: 'Silver',
|
|
specialAssistance: 'Dietary Meal (VGML)',
|
|
originalCabin: 'Business Class',
|
|
actualCabin: 'Economy', // Downgraded
|
|
cabinClass: 'Business Class',
|
|
isHighValue: false,
|
|
seatNumber: '28C',
|
|
ticketNumber: '0162394810241',
|
|
},
|
|
{
|
|
id: 'p-104',
|
|
passengerName: 'Amanda Lewis',
|
|
pnr: 'AL551029P',
|
|
passengerType: 'Adult',
|
|
nationality: 'Canadian',
|
|
loyaltyTier: 'Bronze',
|
|
specialAssistance: 'None',
|
|
originalCabin: 'Economy',
|
|
actualCabin: 'Economy',
|
|
cabinClass: 'Economy',
|
|
isHighValue: false,
|
|
seatNumber: '31D',
|
|
ticketNumber: '0162394810242',
|
|
},
|
|
],
|
|
},
|
|
Q23SXD: {
|
|
flightNumber: 'Q23SXD',
|
|
date: '2026-08-13',
|
|
origin: 'LHR',
|
|
destination: 'CDG',
|
|
category: 'weather',
|
|
scenario: 'cancelled_flight',
|
|
jurisdiction: 'UK261',
|
|
delayDuration: 360,
|
|
status: 'Cancelled',
|
|
description: 'Severe storm and heavy fog over London Heathrow.',
|
|
passengers: [
|
|
{
|
|
id: 'p-201',
|
|
passengerName: 'Robert Vance',
|
|
pnr: 'RV992104K',
|
|
passengerType: 'VIP Adult',
|
|
nationality: 'British',
|
|
loyaltyTier: 'Platinum',
|
|
specialAssistance: 'None',
|
|
originalCabin: 'First Class',
|
|
actualCabin: 'Business Class',
|
|
cabinClass: 'First Class',
|
|
isHighValue: true,
|
|
seatNumber: '1B',
|
|
ticketNumber: '1259920194812',
|
|
},
|
|
{
|
|
id: 'p-202',
|
|
passengerName: 'Emma Watson',
|
|
pnr: 'EW771029M',
|
|
passengerType: 'High Value Adult',
|
|
nationality: 'French',
|
|
loyaltyTier: 'Gold',
|
|
specialAssistance: 'Dietary Meal',
|
|
originalCabin: 'Business Class',
|
|
actualCabin: 'Business Class',
|
|
cabinClass: 'Business Class',
|
|
isHighValue: true,
|
|
seatNumber: '6D',
|
|
ticketNumber: '1259920194813',
|
|
},
|
|
{
|
|
id: 'p-203',
|
|
passengerName: 'David Miller',
|
|
pnr: 'DM334190Q',
|
|
passengerType: 'Adult',
|
|
nationality: 'Australian',
|
|
loyaltyTier: 'Regular',
|
|
specialAssistance: 'Wheelchair (WCHR)',
|
|
originalCabin: 'Economy',
|
|
actualCabin: 'Economy',
|
|
cabinClass: 'Economy',
|
|
isHighValue: false,
|
|
seatNumber: '19A',
|
|
ticketNumber: '1259920194814',
|
|
},
|
|
],
|
|
},
|
|
AZ404: {
|
|
flightNumber: 'AZ404',
|
|
date: '2026-08-13',
|
|
origin: 'SFO',
|
|
destination: 'NRT',
|
|
category: 'travel_exp',
|
|
scenario: 'missed_connection',
|
|
jurisdiction: 'US_DOT',
|
|
delayDuration: 180,
|
|
status: 'Delayed',
|
|
description: 'Late arrival of incoming aircraft causing connection breakdown.',
|
|
passengers: [
|
|
{
|
|
id: 'p-301',
|
|
passengerName: 'Kaito Tanaka',
|
|
pnr: 'KT883192Z',
|
|
passengerType: 'High Value Adult',
|
|
nationality: 'Japanese',
|
|
loyaltyTier: 'Platinum',
|
|
specialAssistance: 'None',
|
|
originalCabin: 'Business Class',
|
|
actualCabin: 'Business Class',
|
|
cabinClass: 'Business Class',
|
|
isHighValue: true,
|
|
seatNumber: '11K',
|
|
ticketNumber: '0571120938491',
|
|
},
|
|
{
|
|
id: 'p-302',
|
|
passengerName: 'Lisa Ray',
|
|
pnr: 'LR110293Y',
|
|
passengerType: 'Adult',
|
|
nationality: 'American',
|
|
loyaltyTier: 'Silver',
|
|
specialAssistance: 'Unaccompanied Minor',
|
|
originalCabin: 'Premium Economy',
|
|
actualCabin: 'Economy',
|
|
cabinClass: 'Premium Economy',
|
|
isHighValue: false,
|
|
seatNumber: '16C',
|
|
ticketNumber: '0571120938492',
|
|
},
|
|
{
|
|
id: 'p-303',
|
|
passengerName: 'Carlos Gomez',
|
|
pnr: 'CG559102X',
|
|
passengerType: 'VIP Adult',
|
|
nationality: 'Mexican',
|
|
loyaltyTier: 'Gold',
|
|
specialAssistance: 'Medical Assistance',
|
|
originalCabin: 'Business Class',
|
|
actualCabin: 'Business Class',
|
|
cabinClass: 'Business Class',
|
|
isHighValue: true,
|
|
seatNumber: '8A',
|
|
ticketNumber: '0571120938493',
|
|
},
|
|
],
|
|
},
|
|
BA178: {
|
|
flightNumber: 'BA178',
|
|
date: '2026-08-15',
|
|
origin: 'JFK',
|
|
destination: 'LHR',
|
|
category: 'flight_ops',
|
|
scenario: 'delayed_flight',
|
|
jurisdiction: 'UK261',
|
|
delayDuration: 300,
|
|
status: 'Delayed',
|
|
description: 'Air traffic control delay on transatlantic sector.',
|
|
passengers: [
|
|
{
|
|
id: 'p-401',
|
|
passengerName: 'Harrison Ford',
|
|
pnr: 'HF908123A',
|
|
passengerType: 'VIP Adult',
|
|
nationality: 'American',
|
|
loyaltyTier: 'Platinum',
|
|
specialAssistance: 'None',
|
|
originalCabin: 'First Class',
|
|
actualCabin: 'First Class',
|
|
cabinClass: 'First Class',
|
|
isHighValue: true,
|
|
seatNumber: '2A',
|
|
ticketNumber: '1250912837192',
|
|
},
|
|
{
|
|
id: 'p-402',
|
|
passengerName: 'Clara Oswald',
|
|
pnr: 'CO449182B',
|
|
passengerType: 'High Value Adult',
|
|
nationality: 'British',
|
|
loyaltyTier: 'Gold',
|
|
specialAssistance: 'None',
|
|
originalCabin: 'Business Class',
|
|
actualCabin: 'Premium Economy',
|
|
cabinClass: 'Business Class',
|
|
isHighValue: true,
|
|
seatNumber: '12E',
|
|
ticketNumber: '1250912837193',
|
|
},
|
|
],
|
|
},
|
|
EK202: {
|
|
flightNumber: 'EK202',
|
|
date: '2026-08-14',
|
|
origin: 'JFK',
|
|
destination: 'DXB',
|
|
category: 'weather',
|
|
scenario: 'delayed_flight',
|
|
jurisdiction: 'US_DOT',
|
|
delayDuration: 210,
|
|
status: 'Delayed',
|
|
description: 'Severe thunderstorm delay prior to pushback.',
|
|
passengers: [
|
|
{
|
|
id: 'p-501',
|
|
passengerName: 'Tariq Al-Mansoor',
|
|
pnr: 'TM771920K',
|
|
passengerType: 'VIP Adult',
|
|
nationality: 'Emirati',
|
|
loyaltyTier: 'Platinum',
|
|
specialAssistance: 'None',
|
|
originalCabin: 'First Class',
|
|
actualCabin: 'First Class',
|
|
cabinClass: 'First Class',
|
|
isHighValue: true,
|
|
seatNumber: '1A',
|
|
ticketNumber: '1769910293841',
|
|
},
|
|
{
|
|
id: 'p-502',
|
|
passengerName: 'Fatima Al-Sayed',
|
|
pnr: 'FA882019L',
|
|
passengerType: 'High Value Adult',
|
|
nationality: 'Emirati',
|
|
loyaltyTier: 'Gold',
|
|
specialAssistance: 'Dietary Meal',
|
|
originalCabin: 'Business Class',
|
|
actualCabin: 'Business Class',
|
|
cabinClass: 'Business Class',
|
|
isHighValue: true,
|
|
seatNumber: '7K',
|
|
ticketNumber: '1769910293842',
|
|
},
|
|
],
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Get options list of flight numbers for dropdown selection
|
|
*/
|
|
export function getMockFlightNumbers(): { label: string; value: string; description: string }[] {
|
|
return Object.values(MOCK_DISRUPTIONS).map((item) => ({
|
|
label: `${item.flightNumber} (${item.origin} → ${item.destination} • ${item.delayDuration}m delay)`,
|
|
value: item.flightNumber,
|
|
description: item.description || '',
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Get disruption detail for a given flight number or PNR reference
|
|
*/
|
|
export function getMockDisruptionByFlightNumber(query: string): MockDisruption | undefined {
|
|
if (!query) return undefined;
|
|
const upper = query.trim().toUpperCase();
|
|
|
|
// 1. Direct flight number match
|
|
const flightKey = Object.keys(MOCK_DISRUPTIONS).find((k) => k.toUpperCase() === upper);
|
|
if (flightKey) return MOCK_DISRUPTIONS[flightKey];
|
|
|
|
// 2. Direct PNR match search across flights
|
|
for (const item of Object.values(MOCK_DISRUPTIONS)) {
|
|
const match = item.passengers.some((p) => p.pnr.toUpperCase() === upper);
|
|
if (match) return item;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* Get list of passengers for a flight
|
|
*/
|
|
export function getPassengersForFlight(flightNumber: string): MockPassenger[] {
|
|
const disruption = getMockDisruptionByFlightNumber(flightNumber);
|
|
return disruption ? disruption.passengers : [];
|
|
}
|
|
|
|
/**
|
|
* Get specific passenger details by flight number and PNR
|
|
*/
|
|
export function getMockPassengerByPnr(flightNumber: string, pnr: string): MockPassenger | undefined {
|
|
const passengers = getPassengersForFlight(flightNumber);
|
|
if (!pnr) return undefined;
|
|
const upperPnr = pnr.trim().toUpperCase();
|
|
return passengers.find((p) => p.pnr.toUpperCase() === upperPnr);
|
|
}
|
|
|
|
/**
|
|
* Search across flights and PNRs, returning disruption and optionally matched passenger ID
|
|
*/
|
|
export function searchDisruptionOrPassenger(query: string): { disruption?: MockDisruption; matchedPassengerId?: string } {
|
|
if (!query) return {};
|
|
const upper = query.trim().toUpperCase();
|
|
|
|
// Search flight number
|
|
const flightKey = Object.keys(MOCK_DISRUPTIONS).find((k) => k.toUpperCase() === upper);
|
|
if (flightKey) {
|
|
return { disruption: MOCK_DISRUPTIONS[flightKey] };
|
|
}
|
|
|
|
// Search PNR
|
|
for (const item of Object.values(MOCK_DISRUPTIONS)) {
|
|
const passenger = item.passengers.find((p) => p.pnr.toUpperCase() === upper);
|
|
if (passenger) {
|
|
return { disruption: item, matchedPassengerId: passenger.id };
|
|
}
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
/**
|
|
* Get all mock disruptions
|
|
*/
|
|
export function getAllMockDisruptions(): MockDisruption[] {
|
|
return Object.values(MOCK_DISRUPTIONS);
|
|
}
|