ShonaPay

Services How It Works Partners FAQ Contact

Stay Connected Anywhere in the World

Get mobile top-ups, global eSIM plans and access to healthcare services through trusted providers.

✓ Trusted Global Partners
✓ Secure Transactions
✓ Instant Activation
100+
Countries Supported
24/7
Service Availability
3
Trusted Service Categories

Flights

Search worldwide flights powered by Shonapay Travel

Flight Results

Search for flights to see available options.

/* ========================================================== SHONAPAY FLIGHT SEARCH ENGINE EDITED SECTION 4/10 CSS PART 1 - CORE SEARCH INTERFACE =========================================================== */ :root { --shonapay-primary: #0ea5e9; --shonapay-primary-dark: #0284c7; --text-main: #0f172a; --text-secondary: #64748b; --border: #cbd5e1; --background-soft: #f8fafc; } /* ========================================================== MAIN WRAPPER =========================================================== */ .shonapay-flight-wrapper { width:100%; max-width:1200px; margin:20px auto; padding:0 20px; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } /* ========================================================== SEARCH CARD =========================================================== */ .shonapay-flight-card { background:#ffffff; border-radius:20px; padding:24px; border:1px solid #e2e8f0; box-shadow: 0 10px 30px rgba(15,23,42,.08); } /* ========================================================== HEADER =========================================================== */ .flight-header { margin-bottom:20px; } .flight-brand { display:flex; align-items:center; gap:12px; } .flight-icon { font-size:32px; } .flight-brand h2 { margin:0 0 4px; color:var(--text-main); font-size:24px; font-weight:800; } .flight-brand p { margin:0; color:var(--text-secondary); font-size:14px; } /* ========================================================== TRIP MODE TABS =========================================================== */ .flight-tabs { display:flex; gap:8px; margin-bottom:20px; border-bottom: 1px solid #e2e8f0; padding-bottom:12px; } .flight-tab { border:1px solid var(--border); background:white; color:#334155; padding:9px 18px; border-radius:10px; cursor:pointer; font-size:14px; font-weight:700; transition:.2s ease; } .flight-tab:hover { border-color:var(--shonapay-primary); } .flight-tab.active { background:var(--shonapay-primary); border-color:var(--shonapay-primary); color:white; } /* ========================================================== MAIN FLIGHT LEG LAYOUT =========================================================== */ .flight-leg { display:grid; grid-template-columns: minmax(180px,1fr) 46px minmax(180px,1fr) minmax(150px,0.8fr) minmax(150px,0.8fr); gap:12px; align-items:end; } /* ========================================================== INPUT MODULES =========================================================== */ .airport-field, .date-field { display:flex; flex-direction:column; gap:6px; position:relative; } .airport-field label, .date-field label { font-size:13px; font-weight:700; color:#475569; } .airport-field input, .date-field input { width:100%; height:46px; box-sizing:border-box; padding:12px; border-radius:10px; border:1px solid var(--border); font-size:14px; color:var(--text-main); background:white; } .airport-field input:focus-visible, .date-field input:focus-visible { outline: 3px solid rgba(14,165,233,.25); border-color: var(--shonapay-primary); } /* ========================================================== SWAP BUTTON =========================================================== */ .swap-airports { width:42px; height:42px; border-radius:50%; border: 1px solid var(--border); background:white; color:#475569; cursor:pointer; display:flex; align-items:center; justify-content:center; font-size:18px; margin-bottom:2px; } .swap-airports:hover { color:var(--shonapay-primary); border-color:var(--shonapay-primary); } /* ========================================================== FLEXIBLE DATE OPTION =========================================================== */ .flexible-date-options { margin-top:16px; } .checkbox-row { display:flex; align-items:center; gap:8px; font-size:14px; color:#334155; cursor:pointer; } .checkbox-row span { color:var(--text-secondary); font-size:13px; } /* ========================================================== BUTTON FOOTER =========================================================== */ .flight-form-footer { display:flex; justify-content:space-between; align-items:center; margin-top:20px; position:relative; } .search-flight-button { height:46px; padding:0 28px; border:none; border-radius:10px; background:var(--shonapay-primary); color:white; font-size:15px; font-weight:800; cursor:pointer; transition:.2s ease; } .search-flight-button:hover { background:var(--shonapay-primary-dark); } .search-flight-button:disabled { opacity:.6; cursor:not-allowed; } /* ========================================================== SHONAPAY FLIGHT SEARCH ENGINE EDITED SECTION 5/10 CSS PART 2 - TRAVELLER POPUP + RESULTS FOUNDATION =========================================================== */ /* ========================================================== TRAVELLER SELECTOR BUTTON =========================================================== */ .traveller-selector { min-width:220px; height:46px; padding:8px 14px; border-radius:10px; border:1px solid #cbd5e1; background:#ffffff; display:flex; flex-direction:column; justify-content:center; align-items:flex-start; cursor:pointer; text-align:left; } .traveller-title { font-size:11px; text-transform:uppercase; font-weight:800; color:#64748b; } .traveller-summary { font-size:14px; font-weight:700; color:#0f172a; } /* ========================================================== TRAVELLER POPUP =========================================================== */ .traveller-popup { position:absolute; right:0; top:calc(100% + 10px); width:340px; padding:22px; background:#ffffff; border-radius:16px; border: 1px solid #e2e8f0; box-shadow: 0 20px 45px rgba(15,23,42,.15); z-index:5000; } .traveller-popup[hidden] { display:none; } .traveller-popup h3 { margin:0 0 18px; font-size:18px; color:#0f172a; } /* ========================================================== TRAVELLER ROWS =========================================================== */ .traveller-row { display:flex; justify-content:space-between; align-items:center; padding:12px 0; } .traveller-description { display:flex; flex-direction:column; } .traveller-description strong { font-size:15px; color:#0f172a; } .traveller-description small { font-size:12px; color:#64748b; } /* ========================================================== COUNTERS =========================================================== */ .counter { display:flex; align-items:center; gap:12px; } .counter button { width:32px; height:32px; border-radius:50%; border:1px solid #cbd5e1; background:white; cursor:pointer; font-size:18px; line-height:1; } .counter button:hover { border-color:#0ea5e9; color:#0ea5e9; } .counter span { min-width:20px; text-align:center; font-weight:700; } /* ========================================================== CABIN OPTIONS =========================================================== */ .cabin-options { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:12px; } .cabin-option { padding:10px; border-radius:8px; border:1px solid #cbd5e1; background:white; cursor:pointer; font-weight:700; font-size:13px; } .cabin-option.active { background:#0ea5e9; border-color:#0ea5e9; color:white; } /* ========================================================== RESULTS AREA =========================================================== */ .flight-results-section { margin-top:35px; } .results-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; } .results-header h2 { margin:0; color:#0f172a; font-size:22px; } .results-placeholder, .results-loader { padding:40px; border-radius:16px; background:white; border:1px dashed #cbd5e1; text-align:center; color:#64748b; } .results-grid { display:flex; flex-direction:column; gap:16px; } /* ========================================================== FLIGHT RESULT CARD FOUNDATION =========================================================== */ .flight-result-card { background:white; border-radius:16px; border:1px solid #e2e8f0; padding:18px; transition:.2s ease; } .flight-result-card:hover { box-shadow: 0 10px 25px rgba(15,23,42,.08); border-color:#bae6fd; } .flight-main-row { display:flex; justify-content:space-between; gap:20px; align-items:center; } .flight-segment { flex:1; } .airline-name { font-weight:800; color:#0f172a; } .flight-pricing-block { display:flex; flex-direction:column; align-items:flex-end; gap:10px; } .flight-price { font-size:20px; font-weight:900; color:#0f172a; } .select-flight-btn { background:#0ea5e9; color:white; border:none; padding:10px 18px; border-radius:8px; cursor:pointer; font-weight:700; } /* ========================================================== SHONAPAY FLIGHT SEARCH ENGINE EDITED SECTION 6/10 CSS PART 3 - BOOKING MODAL + RESPONSIVE DESIGN =========================================================== */ /* ========================================================== BOOKING MODAL OVERLAY =========================================================== */ .booking-modal { position:fixed; inset:0; display:flex; align-items:center; justify-content:center; background: rgba(15,23,42,.65); backdrop-filter:blur(5px); z-index:99999; padding:20px; } .booking-modal[hidden] { display:none !important; } /* ========================================================== BOOKING BOX =========================================================== */ .booking-box { position:relative; width:100%; max-width:520px; max-height:90vh; overflow:hidden; background:#ffffff; border-radius:20px; padding:30px; box-shadow: 0 25px 60px rgba(0,0,0,.25); display:flex; flex-direction:column; } .booking-box h2 { margin:0 0 10px; font-size:22px; font-weight:800; color:#0f172a; } /* ========================================================== CLOSE BUTTON =========================================================== */ .close-booking { position:absolute; top:14px; right:18px; width:36px; height:36px; border:none; background:transparent; color:#64748b; font-size:28px; cursor:pointer; } .close-booking:hover { color:#0f172a; } /* ========================================================== SELECTED FLIGHT SUMMARY =========================================================== */ .booking-summary-badge { margin-bottom:18px; padding:10px 14px; border-radius:10px; background:#f0f9ff; color:#0284c7; font-size:14px; font-weight:700; } /* ========================================================== PASSENGER SCROLL AREA =========================================================== */ .passenger-input-container { overflow-y:auto; flex:1; padding-right:5px; margin-bottom:20px; } /* ========================================================== PASSENGER CARD =========================================================== */ .passenger-form-group { padding:18px; margin-bottom:15px; border-radius:14px; background:#f8fafc; border:1px solid #e2e8f0; } .passenger-form-group h3 { margin:0 0 14px; font-size:15px; color:#334155; } /* ========================================================== FORM ROWS =========================================================== */ .form-row { display:flex; gap:12px; margin-bottom:12px; } .input-field { flex:1; display:flex; flex-direction:column; gap:5px; } .input-field label { font-size:12px; font-weight:700; color:#475569; } .booking-box input { width:100%; box-sizing:border-box; padding:11px 12px; border-radius:8px; border:1px solid #cbd5e1; font-size:14px; color:#0f172a; } .booking-box input:focus-visible { outline: 3px solid rgba(14,165,233,.25); border-color:#0ea5e9; } /* ========================================================== PAYMENT SUMMARY FUTURE AREA =========================================================== */ .payment-summary { margin-bottom:15px; padding:15px; border-radius:10px; background:#f8fafc; } /* ========================================================== CONFIRM BUTTON =========================================================== */ .confirm-booking { width:100%; height:48px; border:none; border-radius:10px; background:#0ea5e9; color:white; font-size:16px; font-weight:800; cursor:pointer; } .confirm-booking:hover { background:#0284c7; } .confirm-booking:focus-visible { outline: 3px solid rgba(14,165,233,.35); } /* ========================================================== SPINNER =========================================================== */ .spinner { width:32px; height:32px; margin:0 auto 15px; border-radius:50%; border: 4px solid #e0f2fe; border-top-color:#0ea5e9; animation: spin .8s linear infinite; } @keyframes spin { to { transform:rotate(360deg); } } /* ========================================================== TABLET RESPONSIVE =========================================================== */ @media(max-width:920px){ .flight-leg { grid-template-columns: 1fr 46px 1fr; } .date-field { grid-column:span 1; } } /* ========================================================== MOBILE SEARCH LAYOUT =========================================================== */ @media(max-width:600px){ .shonapay-flight-card { padding:18px; } .flight-leg { grid-template-columns:1fr; } .swap-airports { margin:auto; } .flight-form-footer { flex-direction:column; gap:12px; align-items:stretch; } .traveller-selector, .search-flight-button { width:100%; } .traveller-popup { left:0; right:auto; width:100%; box-sizing:border-box; } .flight-main-row { flex-direction:column; align-items:stretch; } .flight-pricing-block { align-items:stretch; } .form-row { flex-direction:column; } .booking-box { padding:20px; } } /* ========================================================== SHONAPAY FLIGHT SEARCH ENGINE EDITED SECTION 7/10 JAVASCRIPT PART 1 CONFIGURATION + STATE + AIRPORT AUTOCOMPLETE =========================================================== */ /* ========================================================== API CONFIGURATION =========================================================== */ const SHONAPAY_CONFIG = { backend: "https://YOUR_RENDER_BACKEND_URL", airportEndpoint: "/api/airports/search", duffelSearchEndpoint: "/api/duffel/search", orderEndpoint: "/api/orders/create" }; /* ========================================================== CENTRAL FLIGHT ENGINE STATE =========================================================== */ const FlightEngine = { tripMode: "return", legsCount: 1, maxLegs: 5, flexibleDates: false, flexibleDateRange: 7, passengers:{ adults:1, children:0, infants:0 }, cabin: "economy", baggage:{ checked:false, cabin:true } }; /* ========================================================== GLOBAL VARIABLES =========================================================== */ let selectedFlightOffer = null; let airportSearchTimer = null; let activeAirportIndex = -1; let currentAirportResults = []; /* ========================================================== SAFE TEXT HELPER =========================================================== */ function escapeHTML(value){ return String(value || "") .replaceAll("&","&") .replaceAll("<","<") .replaceAll(">",">") .replaceAll('"',""") .replaceAll("'","'"); } /* ========================================================== AIRPORT SEARCH REQUEST =========================================================== */ async function searchAirports(query){ if(!query || query.length < 2){ return []; } try { const response = await fetch( `${SHONAPAY_CONFIG.backend}${SHONAPAY_CONFIG.airportEndpoint}?q=${encodeURIComponent(query)}` ); if(!response.ok){ throw new Error( "Airport request failed" ); } const data = await response.json(); return Array.isArray(data) ? data : data.data || []; } catch(error){ console.error( "Airport search error:", error ); return []; } } /* ========================================================== AIRPORT AUTOCOMPLETE INITIALISATION =========================================================== */ function setupAirportAutocomplete( input, resultsBox, hiddenCode ){ if(!input || !resultsBox){ return; } resultsBox.setAttribute( "role", "listbox" ); input.addEventListener( "input", ()=>{ clearTimeout( airportSearchTimer ); const query = input.value.trim(); hiddenCode.value = ""; if(query.length < 2){ resultsBox.innerHTML=""; resultsBox.style.display="none"; return; } airportSearchTimer = setTimeout( async()=>{ const airports = await searchAirports(query); currentAirportResults = airports; resultsBox.innerHTML=""; if(!airports.length){ resultsBox.style.display="none"; return; } airports.forEach( (airport,index)=>{ const button = document.createElement( "button" ); button.type = "button"; button.className = "airport-result-item"; button.setAttribute( "role", "option" ); button.dataset.index = index; button.innerHTML = ` ${escapeHTML(airport.city)}
${escapeHTML(airport.name)} ${escapeHTML(airport.iata)} `; button.addEventListener( "click", ()=>{ selectAirport( airport, input, hiddenCode, resultsBox ); } ); resultsBox.appendChild( button ); } ); resultsBox.style.display = "block"; }, 300 ); } ); /* Keyboard support */ input.addEventListener( "keydown", (event)=>{ const items = resultsBox.querySelectorAll( ".airport-result-item" ); if(!items.length){ return; } if(event.key==="ArrowDown"){ event.preventDefault(); activeAirportIndex = Math.min( activeAirportIndex + 1, items.length - 1 ); highlightAirport(items); } if(event.key==="ArrowUp"){ event.preventDefault(); activeAirportIndex = Math.max( activeAirportIndex - 1, 0 ); highlightAirport(items); } if(event.key==="Enter" && activeAirportIndex >=0){ event.preventDefault(); items[activeAirportIndex].click(); } if(event.key==="Escape"){ resultsBox.style.display="none"; } } ); } function highlightAirport(items){ items.forEach( item=> item.classList.remove( "active" ) ); if(items[activeAirportIndex]){ items[activeAirportIndex] .classList.add( "active" ); } } function selectAirport( airport, input, hiddenCode, resultsBox ){ input.value = `${airport.city} (${airport.iata})`; hiddenCode.value = airport.iata; resultsBox.style.display = "none"; activeAirportIndex = -1; input.dispatchEvent( new Event( "change", { bubbles:true } ) ); } /* ========================================================== CONNECT LEG FIELDS =========================================================== */ function initialiseLegFields( legElement ){ const origin = legElement.querySelector( ".origin-input" ); const originResults = legElement.querySelector( ".origin-results" ); const originCode = legElement.querySelector( ".origin-code" ); const destination = legElement.querySelector( ".destination-input" ); const destinationResults = legElement.querySelector( ".destination-results" ); const destinationCode = legElement.querySelector( ".destination-code" ); setupAirportAutocomplete( origin, originResults, originCode ); setupAirportAutocomplete( destination, destinationResults, destinationCode ); } /* ========================================================== CLOSE AIRPORT DROPDOWNS =========================================================== */ document.addEventListener( "click", (event)=>{ document .querySelectorAll( ".airport-results" ) .forEach(box=>{ const parent = box.closest( ".airport-field" ); if( parent && !parent.contains( event.target ) ){ box.style.display = "none"; } }); } ); /* ========================================================== SHONAPAY FLIGHT SEARCH ENGINE EDITED SECTION 8/10 JAVASCRIPT PART 2 DATE ENGINE + TRIP MODES + DUFFEL PAYLOAD =========================================================== */ /* ========================================================== DATE HELPERS =========================================================== */ function getLocalTodayISO(){ const today = new Date(); const year = today.getFullYear(); const month = String( today.getMonth()+1 ).padStart(2,"0"); const day = String( today.getDate() ).padStart(2,"0"); return `${year}-${month}-${day}`; } function initialiseLegDates( legElement ){ const departure = legElement.querySelector( ".departure-date" ); const returning = legElement.querySelector( ".return-date" ); const minimum = getLocalTodayISO(); if(departure){ departure.min = minimum; departure.addEventListener( "change", ()=>{ if(returning){ returning.min = departure.value; if( returning.value && returning.value < departure.value ){ returning.value = departure.value; } } } ); } if(returning){ returning.min = minimum; } } /* ========================================================== FLEXIBLE DATE STATE =========================================================== */ function initialiseFlexibleDates(){ const checkbox = document.getElementById( "flexibleDates" ); if(!checkbox){ return; } checkbox.addEventListener( "change", ()=>{ FlightEngine.flexibleDates = checkbox.checked; } ); } /* ========================================================== RETURN DATE VISIBILITY =========================================================== */ function updateReturnVisibility( mode ){ document .querySelectorAll( ".flight-leg" ) .forEach( leg=>{ const wrapper = leg.querySelector( ".return-date-wrapper" ); const input = leg.querySelector( ".return-date" ); if(!wrapper || !input){ return; } if(mode==="return"){ wrapper.style.display = "flex"; input.disabled = false; input.required = true; }else{ wrapper.style.display = "none"; input.disabled = true; input.required = false; } } ); } /* ========================================================== TAB CONTROLS =========================================================== */ function setupTabControls(){ document .querySelectorAll( ".flight-tab" ) .forEach( tab=>{ tab.addEventListener( "click", ()=>{ document .querySelectorAll( ".flight-tab" ) .forEach( item=>{ item.classList.remove( "active" ); item.setAttribute( "aria-selected", "false" ); } ); tab.classList.add( "active" ); tab.setAttribute( "aria-selected", "true" ); FlightEngine.tripMode = tab.dataset.trip; updateReturnVisibility( FlightEngine.tripMode ); } ); } ); } /* ========================================================== DATE VALIDATION =========================================================== */ function validateAllLegDates(){ let valid = true; const legs = document.querySelectorAll( ".flight-leg" ); legs.forEach( (leg,index)=>{ const departure = leg.querySelector( ".departure-date" ); const returning = leg.querySelector( ".return-date" ); if( !departure || !departure.value ){ alert( `Please select departure date for flight ${index+1}` ); valid = false; return; } if( FlightEngine.tripMode==="return" && returning && returning.value && returning.value < departure.value ){ alert( "Return date cannot be before departure." ); valid = false; } } ); return valid; } /* ========================================================== AIRPORT SWAP =========================================================== */ function setupAirportSwap(){ document .querySelectorAll( ".swap-airports" ) .forEach( button=>{ button.addEventListener( "click", ()=>{ const leg = button.closest( ".flight-leg" ); const origin = leg.querySelector( ".origin-input" ); const destination = leg.querySelector( ".destination-input" ); const originCode = leg.querySelector( ".origin-code" ); const destinationCode = leg.querySelector( ".destination-code" ); if( origin && destination ){ [ origin.value, destination.value ] = [ destination.value, origin.value ]; [ originCode.value, destinationCode.value ] = [ destinationCode.value, originCode.value ]; } } ); } ); } /* ========================================================== DUFFEL OFFER REQUEST PAYLOAD =========================================================== */ function buildDuffelPayload(){ const slices = []; document .querySelectorAll( ".flight-leg" ) .forEach( leg=>{ const origin = leg.querySelector( ".origin-code" )?.value; const destination = leg.querySelector( ".destination-code" )?.value; const departure = leg.querySelector( ".departure-date" )?.value; if( !origin || !destination || !departure ){ return; } slices.push({ origin, destination, departure_date: departure }); if( FlightEngine.tripMode==="return" ){ const returnDate = leg.querySelector( ".return-date" )?.value; if(returnDate){ slices.push({ origin: destination, destination: origin, departure_date: returnDate }); } } } ); const passengers = []; for( let i=0; i No flights found. Please try another date.

`; } return; } if(placeholder){ placeholder.setAttribute( "hidden", "true" ); } grid.removeAttribute( "hidden" ); if(count){ count.textContent = `${offers.length} flights available`; } offers.forEach( ( offer, index )=>{ const slice = offer ?.slices ?. [0]; const segments = slice ?.segments || []; const first = segments[0]; const last = segments[ segments.length-1 ]; const stops = getStops( segments ); const card = document.createElement( "article" ); card.className = "flight-result-card"; card.innerHTML = `
${escapeHTML( getAirlineName(first) )}
${ formatFlightTime( first?.departing_at ) } ${ first?.origin ?.iata_code || "" }
${ formatDuration( slice?.duration ) } ${ stops === 0 ? "Non-stop" : `${stops} stop${stops>1?"s":""}` }
${ formatFlightTime( last?.arriving_at ) } ${ last?.destination ?.iata_code || "" }
${ formatCurrency( offer.total_amount, offer.total_currency ) }
`; const button = card.querySelector( ".select-flight-btn" ); button.offer = offer; grid.appendChild( card ); } ); } /* ========================================================== RESULT BUTTON EVENT DELEGATION =========================================================== */ function setupResultSelection(){ const grid = document.getElementById( "resultsGrid" ); if(!grid){ return; } grid.addEventListener( "click", (event)=>{ const button = event.target.closest( ".select-flight-btn" ); if( !button ){ return; } selectedFlightOffer = button.offer; openBookingPreparation( selectedFlightOffer ); } ); } /* ========================================================== SHONAPAY FLIGHT SEARCH ENGINE EDITED SECTION 10/10 JAVASCRIPT PART 4 FRONTEND CONTROLLER + TRAVELLER + BOOKING =========================================================== */ /* ========================================================== OPEN BOOKING PREPARATION =========================================================== */ function openBookingPreparation( offer ){ selectedFlightOffer = offer; const modal = document.getElementById( "bookingModal" ); const container = document.getElementById( "passengerInputContainer" ); const summary = document.getElementById( "bookingSummaryBadge" ); if( !modal || !container ){ return; } if(summary){ summary.textContent = `${offer.owner?.name || "Airline"} | ${formatCurrency( offer.total_amount, offer.total_currency )}`; } container.innerHTML = ""; let passengerNumber = 0; function createPassengerFields( index, title ){ return `

${title}

`; } for( let i=0; i{ popup.toggleAttribute( "hidden" ); popup.classList.toggle( "show" ); } ); popup.addEventListener( "click", event=>{ const target = event.target; if( target.classList.contains( "counter-plus" ) || target.classList.contains( "counter-minus" ) ){ const type = target.dataset.target; const display = document.getElementById( type ); let value = Number( display.textContent ); if( target.classList.contains( "counter-plus" ) ){ value++; }else{ if( type==="adultCount" ){ value = Math.max( 1, value-1 ); }else{ value = Math.max( 0, value-1 ); } } display.textContent = value; if(type==="adultCount") FlightEngine.passengers.adults=value; if(type==="childCount") FlightEngine.passengers.children=value; if(type==="infantCount") FlightEngine.passengers.infants=value; } if( target.classList.contains( "cabin-option" ) ){ popup .querySelectorAll( ".cabin-option" ) .forEach( item=> item.classList.remove( "active" ) ); target.classList.add( "active" ); FlightEngine.cabin = target.dataset.cabin; } } ); document .getElementById( "closeTravellerPopup" ) ?.addEventListener( "click", ()=>{ popup.setAttribute( "hidden", "true" ); popup.classList.remove( "show" ); const total = FlightEngine.passengers.adults + FlightEngine.passengers.children + FlightEngine.passengers.infants; document .querySelector( ".traveller-summary" ) .textContent = `${total} Traveller${total>1?"s":""} · ${ FlightEngine.cabin.replace("_"," ") }`; } ); } /* ========================================================== PASSENGER SUBMISSION =========================================================== */ function setupPassengerForm(){ const form = document.getElementById( "shonapayPassengerForm" ); if(!form){ return; } form.addEventListener( "submit", event=>{ event.preventDefault(); const passengers = []; document .querySelectorAll( ".passenger-form-group" ) .forEach( group=>{ passengers.push({ given_name: group .querySelector( ".p-first" ) .value .trim(), family_name: group .querySelector( ".p-last" ) .value .trim(), born_on: group .querySelector( ".p-dob" ) .value, nationality: group .querySelector( ".p-nationality" ) .value .toUpperCase(), identity_documents:[{ type: "passport", unique_identifier: group .querySelector( ".p-passport" ) .value .trim(), issuing_country: group .querySelector( ".p-nationality" ) .value .toUpperCase() }] }); } ); const orderPayload = { offer_id: selectedFlightOffer.id, passengers }; console.log( "Duffel Order Payload:", orderPayload ); alert( "Passenger details captured. Ready for Duffel order creation." ); } ); } /* ========================================================== MAIN STARTUP CONTROLLER =========================================================== */ document.addEventListener( "DOMContentLoaded", ()=>{ setupTabControls(); setupAirportSwap(); initialiseFlexibleDates(); document .querySelectorAll( ".flight-leg" ) .forEach( leg=>{ initialiseLegFields( leg ); initialiseLegDates( leg ); } ); setupTravellerPopup(); setupResultSelection(); setupPassengerForm(); document .getElementById( "closeBooking" ) ?.addEventListener( "click", closeBookingModal ); const form = document.getElementById( "shonapayFlightSearchForm" ); form?.addEventListener( "submit", async event=>{ event.preventDefault(); if( !validateAllLegDates() ){ return; } const loader = document.getElementById( "resultsLoader" ); loader?.removeAttribute( "hidden" ); try{ const response = await fetch( `${SHONAPAY_CONFIG.backend}${SHONAPAY_CONFIG.duffelSearchEndpoint}`, { method:"POST", headers:{ "Content-Type": "application/json" }, body: JSON.stringify( buildDuffelPayload() ) } ); const data = await response.json(); renderFlightResults( data ); }catch(error){ console.error( error ); alert( "Flight search failed." ); } } ); } );

Mobile Connect

🔍
Arrives online in seconds...
Start top-up

Travel Data

🔍

Medical Care

  • ✓ English & Multi-lingual support
  • ✓ Over 150 countries covered
  • ✓ 24/7 Urgent assistance desk

How It Works?

Simple 3-step process to get started in minutes.

1

Choose Service

Select eSIM, mobile top-up, or medical assistance services.

2

Complete Checkout

Pay securely via encrypted primary reseller system networks.

3

Instant Activation

Your target utility activates immediately worldwide.

Trusted Partners

We connect users with highly compliant, verified global infrastructure engines.

Airalo eSIM
Ding Platform
EKTA Insurance
Air Doctor Network

Frequently Asked Questions

Everything you need to know before using ShonaPay.

Is ShonaPay a healthcare provider or travel underwriter?

No. ShonaPay functions as a central marketplace application layer. We securely forward client workflows directly into certified medical ecosystems like Air Doctor or policy providers like EKTA.

How do I access a telemedicine doctor if I am outside an active region?

Our application features automated failover routing logic. If your destination sits outside Air Doctor's primary clinic system, ShonaPay instantly presents a 24/7 dedicated support phone line bound directly to your insurance policy.

Is payment secure?

Yes. All payments are processed securely through partner platforms with encryption.

Can I use services worldwide?

Yes. Services are available in 150+ countries depending on the provider and configuration.

💬