Auto load staff events

User
$(document).on('click', '.reload-events-staff', function()
{

f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {

$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`

${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}

0/500

`);

//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});
remove click event just run default

Assistant
To **run the AJAX function by default without needing a click**, simply extract the function from the click event and **call it directly** on page load (e.g. within `$(document).ready()` or Framework7's `page:init`).

Here’s the **modified version** of your code:

function loadStaffEvents() {
  f7App.dialog.preloader('Loading events...');
  $.ajax({
    url: `${ApiUrl}today`,
    method: 'POST',
    data: {
      token: TOKEN
    },
    success: function(result, status, xhr) {
      console.log(result);
      var events = JSON.parse(result);
      if (events.result) {
        $('.staff-screen ul.events').html('');
        $('.staff-screen div.events').html('');
        const weekday = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
        $.each(events.data, function(i, val) {
          var eventDatetime = new Date(val.event_datetime);
          var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
          var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
          var dayname = weekday[eventDatetime.getDay()];
          $('.staff-screen div.events').append(`
            <div class="space-y-4 mb-4" data-event-id="${val.event_id}" data-event-date-id="${val.event_date_id}">
              <div class="rounded-lg border border-border/40 card bg-background hover:shadow-lg transition-shadow cursor-pointer">
                <div class="p-6">
                  <div class="flex justify-between items-center">
                    <div>
                      <h3 class="text-xl font-semibold">${val.venue_full}</h3>
                      <p class="text-gray-600">${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} - 
                        ${eventDatetime.toLocaleTimeString('en-US', timeOptions)}</p>
                    </div>
                    <div class="text-right">
                      <div class="inline-flex items-center rounded-full border font-semibold transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 text-foreground border-border px-2.5 py-0.5 text-xs">
                        0/500
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>`);
        });
      } else {
        $('.events').html(`<div class="no-result-item text-center bg-info text-white">${events.message}</div>`);
      }
    },
    error: function(xhr, status, error) {
      f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
    },
    complete: function() {
      f7App.dialog.close();
    }
  });
}

// Call it directly on page load or page init
$(document).ready(function() {
  loadStaffEvents();
});

// OR if you're using Framework7 page event:
$(document).on('page:init', '.page[data-name="staff"]', function (e) {
  loadStaffEvents();
});

✅ **Benefits:**
– No `.click()` event needed.
– You control where and when the event data loads.
– You can still reuse `loadStaffEvents()` anywhere else (e.g. refresh button).

User
framework 7 login with local storage
Assistant
To implement **Framework7 login with Local Storage**, you can follow this approach:

### ✅ What we’ll do:
1. User logs in by entering credentials (you can skip server check for simplicity).
2. Store a flag (e.g., `isLoggedIn = true`) in `localStorage`.
3. On app start, check `localStorage` — if logged in, redirect to home.
4. Else show login screen.

### 🔧 1. HTML (login.html)

<!-- login.html -->
<div class="page" data-name="login">
  <div class="page-content login-screen-content">
    <div class="block">
      <h2>Login</h2>
      <div class="list">
        <ul>
          <li>
            <div class="item-content item-input">
              <div class="item-inner">
                <div class="item-title item-label">Username</div>
                <div class="item-input-wrap">
                  <input type="text" id="username" placeholder="Enter username">
                </div>
              </div>
            </div>
          </li>
          <li>
            <div class="item-content item-input">
              <div class="item-inner">
                <div class="item-title item-label">Password</div>
                <div class="item-input-wrap">
                  <input type="password" id="password" placeholder="Enter password">
                </div>
              </div>
            </div>
          </li>
        </ul>
      </div>
      <div class="block">
        <a href="#" class="button button-fill login-button">Login</a>
      </div>
    </div>
  </div>
</div>

### 🔌 2. JavaScript Logic

document.addEventListener('deviceready', function () {
  // Initialize Framework7 app
  var f7App = new Framework7({
    el: '#app',
    name: 'LoginApp',
    theme: 'auto',
    routes: [
      { path: '/', url: 'pages/home.html' },
      { path: '/login/', url: 'pages/login.html' }
    ]
  });

  var mainView = f7App.views.create('.view-main');

  // Redirect if already logged in
  if (localStorage.getItem('isLoggedIn') === 'true') {
    mainView.router.navigate('/');
  } else {
    mainView.router.navigate('/login/');
  }

  // Handle login button click
  $(document).on('click', '.login-button', function () {
    var username = $('#username').val();
    var password = $('#password').val();

    if (username === 'admin' && password === 'admin') {
      localStorage.setItem('isLoggedIn', 'true');
      mainView.router.navigate('/');
    } else {
      f7App.dialog.alert('Invalid credentials', 'Login Failed');
    }
  });
});

### 🏠 3. Home Page (home.html)

<!-- home.html -->
<div class="page" data-name="home">
  <div class="navbar">
    <div class="navbar-inner">
      <div class="title">Home</div>
      <div class="right">
        <a href="#" class="link logout-button">Logout</a>
      </div>
    </div>
  </div>
  <div class="page-content">
    <div class="block">
      <h2>Welcome!</h2>
      <p>This is the home page.</p>
    </div>
  </div>
</div>

### 🚪 4. Logout Logic

$(document).on('click', '.logout-button', function () {
  localStorage.removeItem('isLoggedIn');
  f7App.views.main.router.navigate('/login/');
});

### ✅ Summary
– 🔐 You simulate login using localStorage.
– 🔁 Redirect to home if already logged in.
– 🚪 Logout clears the login status.

Let me know if you want to include a backend check via AJAX too.

User
How to pair android studion virtual to mobile using qrcode
Assistant
To pair Android Studio's **Device Mirroring** or **ADB over Wi-Fi** with your **real Android device using a QR code**, follow these steps:

### ✅ Requirements:
– Android Studio **Hedgehog** or later
– USB cable (for initial setup)
– Phone running Android 11 or above (preferably)
– Developer options & USB debugging enabled

### 🔄 Option 1: **ADB Pairing via QR Code (No Cable Needed)**

#### 🔧 Step-by-Step Instructions:

1. **Enable Developer Options** on your phone:
– Go to **Settings > About phone** → tap **Build number** 7 times
– Go to **Settings > System > Developer options**

2. **Enable Wireless Debugging**:
– In **Developer options**, turn on **Wireless debugging**

3. **Pair using QR code**:
– In Android Studio:
– Go to **Device Manager** (right sidebar) → Click **+ Pair using Wi-Fi**
– Choose **Pair using QR code**

– On your Android device:
– Still in **Wireless Debugging** → Tap **Pair device with QR code**
– Scan the QR code shown in Android Studio

4. ✅ Done! Your real device will show up under **Connected Devices** in Android Studio.

### 🔁 Option 2: **ADB Over Wi-Fi Using IP and Port (Manual)**

If QR pairing fails, use this method with a USB cable for the first time:

adb usb                     # (optional) ensure USB connection
adb tcpip 5555
adb connect <DEVICE_IP>:5555

You can get the IP from:
– `adb shell ip route`
– or phone’s Wi-Fi settings.

### 📌 Notes:
– QR Code method uses **secure pairing** (Android 11+).
– Works even without USB if Wireless Debugging is supported.
– Make sure both PC and phone are on the **same Wi-Fi network**.

Let me know if you want to mirror the screen or just run/debug apps.

User
ok now paired how to use in android studio
Assistant
Great — since your Android device is now **paired via QR code** and connected for wireless debugging, here’s how to **use it in Android Studio**:

### ✅ Steps to Use Paired Android Device in Android Studio

#### 📱 1. **Check Device Connection**
– Open **Android Studio**
– Go to **Device Manager** (right toolbar)
– Your phone should appear under **"Connected Devices"**
– Name like `Pixel 6a (Wi-Fi)` or similar
– If not, open **Terminal** and run:

adb devices

You should see your device listed as `device`.

#### ▶️ 2. **Run Your App on the Device**
– Open your Android project
– Click the **Run ▶️** button or press `Shift + F10`
– In the **"Select Deployment Target"** window, choose your **Wi-Fi connected phone**
– Click **OK** or **Run**

Android Studio will build the app and install it on your device wirelessly.

#### 🔁 3. **Enable Instant Run (Optional for Speed)**
– Go to **File > Settings > Build, Execution, Deployment > Deployment**
– Enable **"Apply changes…"** to push code without reinstalling the app

#### 🚫 4. **To Disconnect Device Later**
– On your phone:
Go to **Developer options > Wireless debugging** → Tap **Forget all devices**
– Or run in terminal:

adb disconnect <ip>:port

### 🛠 Troubleshooting
| Issue | Solution |
|——-|———-|
| Device not showing | Restart Android Studio, verify `adb devices` shows your phone |
| App not installing | Check if device is unlocked and has enough storage |
| QR pairing fails | Try with USB cable and use `adb tcpip 5555` |

Let me know if you want to **mirror screen**, **debug logs**, or use **ADB commands** directly.

User
we have seen device but how to run
Assistant
Perfect — since your device is **visible in Android Studio**, here’s exactly how to **run your app on it** step-by-step:

### ✅ How to Run Your App on the Paired Android Device

#### 🔁 Step-by-Step:

1. **Open Your Project** in Android Studio.

2. At the top toolbar, locate the **Device dropdown** (next to the green ▶️ Run button).

3. From the dropdown, **select your connected device**:
It should appear like:
`Pixel 6a (Wi-Fi)` or `SM-M14 (192.168.x.x:5555)` depending on your phone.

4. Click the **Run ▶️ button** or press `Shift + F10`.

5. Android Studio will:
– **Build the APK**
– **Install it wirelessly**
– **Launch the app automatically** on your phone

### 📱 On Your Phone
– Ensure the screen is **unlocked**
– You’ll see your app open once it’s successfully deployed

### 🛠 If the device is not listed in dropdown:
– Try clicking **Run ▶️** anyway — a popup will appear to **select device**
– If still not listed:
– Go to **View > Tool Windows > Device Manager**
– Or run `adb devices` to verify it’s connected as `device`

Let me know if:
– You want to enable **live logcat logging**
– You want to **debug** the app using breakpoints
– You need **multiple devices or emulator + real device setup**

User
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.'+error+status+xhr, 'Error');
}
how to get detailed error
Assistant
To get **detailed error output in your AJAX error callback**, you should extract useful parts from the `xhr` object, such as:

– `xhr.status` – HTTP status code (e.g., 404, 500)
– `xhr.statusText` – status description (e.g., "Not Found")
– `xhr.responseText` – raw server response
– `error` – general error message from jQuery
– `status` – error type (like "error", "timeout", "parsererror")

### ✅ Updated Error Function (Verbose Logging):

error: function(xhr, status, error) {
    let detailedMessage = `
      ❌ Status: ${xhr.status} (${xhr.statusText})n
      🧠 Error Type: ${status}n
      📩 Response: ${xhr.responseText || 'No response'}n
      🧾 Error: ${error}
    `;
    
    console.error("AJAX Error Details", {
        status: xhr.status,
        statusText: xhr.statusText,
        responseText: xhr.responseText,
        error: error,
        fullXhr: xhr
    });

    f7App.dialog.alert(detailedMessage, 'Error');
}

### 🛠 Extra Tip for JSON Responses

If your backend returns JSON and you're expecting `result.message`, check:

try {
    const json = JSON.parse(xhr.responseText);
    console.log("Parsed JSON:", json);
} catch (e) {
    console.warn("Response is not valid JSON");
}

This gives you a **clear breakdown** inside both:
– The **alert for the user**
– The **console for debugging**

Let me know if you want to log it to a remote server or alert with a friendly error message instead.

User
xhr.status return 0
Assistant
When `xhr.status` returns **0** in a jQuery AJAX request, it typically means the request **never reached the server properly**, or the browser **blocked it**. Here's what it means and how to fix it.

### 🚨 Causes of `xhr.status == 0`:

| Cause | Description |
|——-|————-|
| ❌ **CORS blocked** | You're making a cross-origin request without proper headers |
| 📡 **No internet / disconnected** | Device has no connection or server is unreachable |
| 🔒 **HTTPS → HTTP** | Mixed content (HTTPS site calling HTTP URL) — blocked by browser |
| ⌛ **Request timed out** | Backend took too long to respond |
| 🔂 **Manually aborted** | AJAX call was aborted using `xhr.abort()` |
| 📁 **Wrong `url` or file path** | Endpoint doesn’t exist or returns a blank response |

### ✅ How to Debug It

Update your error block like this to get more clues:

error: function(xhr, status, error) {
    console.error("AJAX Error", {
        status: xhr.status,                // 0
        statusText: xhr.statusText,        // Often empty
        responseText: xhr.responseText,    // May be empty
        readyState: xhr.readyState,        // 0-4
        errorThrown: error,
        url: this.url                      // URL being requested
    });

    f7App.dialog.alert(`
        ❌ AJAX failed!
        Status: ${xhr.status}
        ReadyState: ${xhr.readyState}
        Error: ${error}
        Response: ${xhr.responseText || 'No response'}
    `, 'Error');
}

### 🛠 Solutions to Try

1. **Check your `url` value**:

url: `${ApiUrl}today` // Make sure ApiUrl is set correctly

– Try logging `ApiUrl` before the AJAX call to ensure it's not undefined.

2. **Add CORS headers on server (if using PHP)**:

header("Access-Control-Allow-Origin: *");
   header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
   header("Access-Control-Allow-Headers: Content-Type, Authorization");

3. **Use HTTPS for both frontend and backend**
If your app is served over HTTPS, your API must also be HTTPS.

4. **Test API directly**:
– Open browser dev tools → Network tab
– Paste the API URL directly to see if it responds

5. **Try using `cordova-plugin-whitelist` (if in Cordova)**:
If you're running this inside a Cordova app:

<access origin="*" />
   <allow-navigation href="*" />
   <allow-intent href="*" />

And ensure plugin is installed:

cordova plugin add cordova-plugin-whitelist

Let me know if you're testing on mobile, localhost, or remote server — I can give more specific advice.

User
document.addEventListener('deviceready', function () {
if (cordova.platformId === 'android') {
var permissions = cordova.plugins.permissions;

permissions.checkPermission(permissions.CAMERA, function (status) {
if (!status.hasPermission) {
// Request permission
permissions.requestPermission(
permissions.CAMERA,
function (status) {
if (status.hasPermission) {
navigator.splashscreen.hide(); // Hide splash after permission
initializeApp(); // Proceed with your app
} else {
navigator.app.exitApp(); // Exit if denied
}
},
function () {
navigator.app.exitApp(); // Exit on request error
}
);
} else {
navigator.splashscreen.hide();
initializeApp(); // Permission already granted
}
});
} else {
navigator.splashscreen.hide(); // For browser/iOS fallback
initializeApp();
}
}, false);
function initializeApp() {

let TOKEN = 'fossettscircustoken';
var eventId = -1;
var eventDateId = -1;
let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';

var scanConfig = {
preferFrontCamera : false, // iOS and Android
showFlipCameraButton : true, // iOS and Android
showTorchButton : true, // iOS and Android
torchOn: false, // Android, launch with the torch switched on (if available)
saveHistory: false, // Android, save scan history (default false)
prompt : "Place a code inside the scan area", // Android
resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
formats : "QR_CODE", // default: all but PDF_417 and RSS_EXPANDED
//orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device
disableAnimations : true, // iOS
disableSuccessBeep: false // iOS and Android
};
$(document).ready(function()
{
$(document).on('page:init', '.page[data-name="home"]', function () {
$('#customer-access').on('click', function () {
f7App.views.main.router.navigate('/customer/');
});
$('#staff-access').on('click', function () {
f7App.views.main.router.navigate('/staff-login/');
});

});

$(document).on('page:init', '.page[data-name="staff-pay-terminal"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('input', '#amountInput', function () {
const amount = parseFloat($(this).val());
const btn = $('#chargeBtn');

if (amount > 0) {
btn.removeClass('disabled color-gray').addClass('color-green');
btn.text('Charge €' + amount.toFixed(2));
} else {
btn.addClass('disabled color-gray').removeClass('color-green');
btn.text('Charge €0.00');
}
});
})
var staffEventsLoaded = false;
$(document).on('page:init', '.page[data-name="staff-tickets"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('click', '.reload-events-staff', function()
{

f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {

$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`

${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}

0/500

`);

//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});

// load events click

$('.reload-events-staff').trigger('click');

$(document).on('click', '.logout-staff', function()
{

localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-check-orders"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
});
$(document).on('page:init', '.page[data-name="staff-dashboard"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-tickets').on('click', function () {
f7App.views.main.router.navigate('/staff-tickets/');
});
$('#open-pay-terminal').on('click', function () {
f7App.views.main.router.navigate('/staff-pay-terminal/');
});
$('#check-orders').on('click', function () {
f7App.views.main.router.navigate('/staff-check-orders/');
});

// load events click
$('.reload-events-staff').trigger('click');
$(document).on('click', '.logout-staff', function()
{

localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-login"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-login-form').on('submit', function (e) {
e.preventDefault();
var email = $('#staff-email').val();
var password = $('#staff-password').val();
f7App.dialog.preloader('Logging in…');
$.ajax({
url: `${ApiUrl}staff_login`,
method: 'POST',
data: {
token: TOKEN,
email: email,
password: password
},
success: function (result, status, xhr) {
var apiResult = JSON.parse(result);
if (apiResult.result) {
f7App.views.main.router.navigate('/staff/');
} else {
$('#login-result').html(apiResult.message);
}
},
error: function (xhr, status, error) {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function () {
// ✅ Hide preloader after AJAX completes
f7App.dialog.close();
}
});
});
});

// Page: Customer
$(document).on('page:init', '.page[data-name="customer"]', function () {
// 👇 Ensure Bootstrap re-binds modal events
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
var sendCode = function(code)
{
$('.scan').prop('disabled', true);
$('.manually').prop('disabled', true);
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ code +' sent to boxoffice, plase wait…');

$.ajax({
url: `${ApiUrl}scan`,
method: 'POST',
data: {
token: TOKEN,
event_date_id: eventDateId,
order_code: code
},
success: function(result,status,xhr)
{
var apiResult = JSON.parse(result);

if ( apiResult.result )
{
$('#scan-result').removeClass('bg-dark').addClass('bg-success').html(apiResult.message+''+apiResult.seating+''+apiResult.tickets);

// reset input to set next code
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html(apiResult.message);
}
},
error: function(xhr,status,error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ result.text +' could not be sent to boxoffice, please try again');
},
complete: function()
{
$('.scan').prop('disabled', false);
$('.manually').prop('disabled', false);
}
});
}

var scanError = function (error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html("Scanning failed: " + error);

f7App.popup.open('#modal-scan-result');
};

var scanSuccess = function(result)
{
if (! result.cancelled )
{
if (eventDateId > -1)
{
sendCode(result.text);
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('You must select an event date to scan tickets');
}
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Scan was cancelled');
}

f7App.popup.open('#modal-scan-result');
};
$(document).on('click', '.reload-events', function()
{

f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {

$('.customer-screen ul.events').html('');

const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
// $('.customer-screen ul.events').append(`
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}
//
//
// `);
$('.customer-screen div.events').append(`

${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}

0/500

`);
// $('.customer-screen ul.events').append(`
//
//
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
// ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} –
// ${val.venue_title} – ${val.venue_full}
//
//
//
//
// `);
// $('.customer-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}`);

});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.'+xhr.statusText+xhr.status, 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});

// load events click
$('.reload-events').trigger('click');

$(document).on('click', '.customer-screen .events .list-group-item', function()
{

$('.customer-screen .events .list-group-item').removeClass('active');
$(this).addClass('active');

$('#scan-info').html($(this).html());

eventId = $(this).attr('data-event-id');
eventDateId = $(this).attr('data-event-date-id');

$('[name="code"]').val(eventId +'.'+ eventDateId +'.');

// first scan on event date click
//cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
f7App.popup.open('#modal-scan-result');

});

$(document).on('click', '.scan', function()
{
cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
});

$(document).on('click', '.manually', function()
{
sendCode($('[name="code"]').val());
});

});

// $('ons-button').on('click', function(e) {
// ons.notification.alert('Button is tapped!');
// })

});

}

above code for fetch event for customer section stopped working its return ajax status 0 in andrdroind but when run in browser its work well

Assistant
Thank you for sharing the full code. The AJAX call in your **Cordova/Framework7 app** is returning `status 0` **only in Android (device or emulator)**, which strongly indicates a **CORS, HTTPS, or network configuration issue specific to Cordova**.

### ✅ Root Cause (Most Likely):

Your AJAX call is to:

let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';

While this works in the **browser**, Cordova apps run in a **WebView sandbox**, and:

– Do **not allow external domains** unless explicitly permitted.
– Require **CORS headers** on the server.
– May block **HTTPS → HTTP** (or vice versa) if not handled correctly.

### ✅ Fix It Step-by-Step:

#### ✅ 1. Add Cordova Whitelist Plugin (if not added):

Run:

cordova plugin add cordova-plugin-whitelist

Then in `config.xml`, add:

<allow-navigation href="*" />
<access origin="*" />
<allow-intent href="*" />

#### ✅ 2. Ensure AndroidManifest Permissions:

Inside your `AndroidManifest.xml`, confirm:

<uses-permission android:name="android.permission.INTERNET" />

#### ✅ 3. Server Must Allow CORS

Your server (`staging.fossettscircus.com`) **must send the right headers**:

In your PHP API backend (`index.php/api/today`), add:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

Place these at the **very top** before any output.

#### ✅ 4. Debug with More Detail

In your `.ajax()` `error` callback, replace with this to inspect further:

error: function(xhr, status, error) {
    console.error("XHR ERROR:", {
        status: xhr.status,
        statusText: xhr.statusText,
        responseText: xhr.responseText,
        readyState: xhr.readyState,
        errorThrown: error,
        headers: xhr.getAllResponseHeaders()
    });
    
    f7App.dialog.alert(`
        ❌ AJAX Failed
        Status: ${xhr.status} (${xhr.statusText})
        Error: ${error}
        Response: ${xhr.responseText}
    `, 'Error');
}

#### 🧪 5. Test with a Localhost Server on Android Device

Sometimes Android WebView blocks requests to `localhost` or `https` servers with self-signed SSL. Try changing:

let ApiUrl = 'http://your-lan-ip/boxoffice/index.php/api/';
// or deploy a test endpoint on a public URL with HTTPS and CORS enabled

### 🧠 Extra Tips

– If you're using `content-security-policy`, loosen it for dev:

<meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval' data: gap:;">

– Android 9+ blocks **cleartext (HTTP)** traffic by default. You must allow it in `network_security_config.xml`.

### ✅ Final Suggestion:

If you want, I can test the live `https://staging.fossettscircus.com/boxoffice/index.php/api/today` URL for proper CORS headers. Just let me know.

Let me know how you're running it (emulator, real device, APK) and I’ll tailor the fix more closely.

User
cors header already present and its working best in cordova run broswer
but I think I have updated android sdk
Assistant
Thanks for the update. Since:

– ✅ CORS headers are present,
– ✅ It works in `cordova run browser`,
– ❌ But fails on **real Android device or emulator** with `status = 0`,
– 💡 And you've **recently updated Android SDK**,

You're likely hitting a **WebView security change in newer Android SDK versions**, especially Android 10+ (SDK 29+).

### ✅ Checklist to Fix Cordova AJAX status 0 on Android:

#### ✅ 1. **Enable `usesCleartextTraffic`** if using HTTP (not needed for HTTPS)
If your API URL is `http://` (not `https://`), Android 9+ blocks it by default.

In `AndroidManifest.xml` inside “:

android:usesCleartextTraffic="true"

And define this inside `res/xml/network_security_config.xml`:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config cleartextTrafficPermitted="true" />
</network-security-config>

Then reference it:

<application
  android:networkSecurityConfig="@xml/network_security_config"
  android:usesCleartextTraffic="true"
  ...>

✅ **Not needed for HTTPS**, but if your domain uses a **self-signed SSL** or weak certificate, that can cause issues too.

#### ✅ 2. **Force Cordova to Use Legacy WebView**
If you're using a new Android WebView (based on Chromium), it may enforce stricter network rules.

Add to `config.xml`:

<preference name="AndroidInsecureFileModeEnabled" value="true" />
<preference name="AndroidXEnabled" value="true" />

You can also try forcing a compatible WebView:

cordova plugin add cordova-plugin-androidx-adapter

#### ✅ 3. **Inspect Dev Logs via `adb logcat`**
Run this in terminal to see real-time logs:

adb logcat | grep chromium

This will often reveal:
– Mixed content errors
– Certificate validation issues
– Blocked cross-origin requests

#### ✅ 4. **Test with Postman or Mobile Browser on Same Device**
Use your **phone’s browser** to open:

https://staging.fossettscircus.com/boxoffice/index.php/api/today

If the result is empty or SSL warns you — then the problem is with:
– SSL cert (not fully trusted)
– Invalid DNS or redirect

#### ✅ 5. **Try Running With Older Target SDK**
Temporarily change `platforms/android/app/build.gradle`:

targetSdkVersion = 30

Or in `config.xml`:

<preference name="android-targetSdkVersion" value="30" />

Then run:

cordova platform remove android
cordova platform add android@latest
cordova build android

### 🧪 Final Debug Help
If still stuck, add a temporary test API with:

<?php
header("Access-Control-Allow-Origin: *");
echo json_encode(["result" => true, "message" => "It works!"]);

Then test that in your app to isolate the API issue vs. SDK/WebView issue.

Let me know your:
– Android version (10/11/12/etc.)
– Cordova version
– Target SDK in `AndroidManifest.xml`

And I’ll guide you precisely!

User
document.addEventListener('deviceready', function () {
if (cordova.platformId === 'android') {
var permissions = cordova.plugins.permissions;

permissions.checkPermission(permissions.CAMERA, function (status) {
if (!status.hasPermission) {
// Request permission
permissions.requestPermission(
permissions.CAMERA,
function (status) {
if (status.hasPermission) {
navigator.splashscreen.hide(); // Hide splash after permission
initializeApp(); // Proceed with your app
} else {
navigator.app.exitApp(); // Exit if denied
}
},
function () {
navigator.app.exitApp(); // Exit on request error
}
);
} else {
navigator.splashscreen.hide();
initializeApp(); // Permission already granted
}
});
} else {
navigator.splashscreen.hide(); // For browser/iOS fallback
initializeApp();
}
}, false);
function initializeApp() {

let TOKEN = 'fossettscircustoken';
var eventId = -1;
var eventDateId = -1;
let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';

var scanConfig = {
preferFrontCamera : false, // iOS and Android
showFlipCameraButton : true, // iOS and Android
showTorchButton : true, // iOS and Android
torchOn: false, // Android, launch with the torch switched on (if available)
saveHistory: false, // Android, save scan history (default false)
prompt : "Place a code inside the scan area", // Android
resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
formats : "QR_CODE", // default: all but PDF_417 and RSS_EXPANDED
//orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device
disableAnimations : true, // iOS
disableSuccessBeep: false // iOS and Android
};
$(document).ready(function()
{
$(document).on('page:init', '.page[data-name="home"]', function () {
$('#customer-access').on('click', function () {
f7App.views.main.router.navigate('/customer/');
});
$('#staff-access').on('click', function () {
f7App.views.main.router.navigate('/staff-login/');
});

});

$(document).on('page:init', '.page[data-name="staff-pay-terminal"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('input', '#amountInput', function () {
const amount = parseFloat($(this).val());
const btn = $('#chargeBtn');

if (amount > 0) {
btn.removeClass('disabled color-gray').addClass('color-green');
btn.text('Charge €' + amount.toFixed(2));
} else {
btn.addClass('disabled color-gray').removeClass('color-green');
btn.text('Charge €0.00');
}
});
})
var staffEventsLoaded = false;
$(document).on('page:init', '.page[data-name="staff-tickets"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('click', '.reload-events-staff', function()
{

f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {

$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`

${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}

0/500

`);

//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});

// load events click

$('.reload-events-staff').trigger('click');

$(document).on('click', '.logout-staff', function()
{

localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-check-orders"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
});
$(document).on('page:init', '.page[data-name="staff-dashboard"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-tickets').on('click', function () {
f7App.views.main.router.navigate('/staff-tickets/');
});
$('#open-pay-terminal').on('click', function () {
f7App.views.main.router.navigate('/staff-pay-terminal/');
});
$('#check-orders').on('click', function () {
f7App.views.main.router.navigate('/staff-check-orders/');
});

// load events click
$('.reload-events-staff').trigger('click');
$(document).on('click', '.logout-staff', function()
{

localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-login"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-login-form').on('submit', function (e) {
e.preventDefault();
var email = $('#staff-email').val();
var password = $('#staff-password').val();
f7App.dialog.preloader('Logging in…');
$.ajax({
url: `${ApiUrl}staff_login`,
method: 'POST',
data: {
token: TOKEN,
email: email,
password: password
},
success: function (result, status, xhr) {
var apiResult = JSON.parse(result);
if (apiResult.result) {
f7App.views.main.router.navigate('/staff/');
} else {
$('#login-result').html(apiResult.message);
}
},
error: function (xhr, status, error) {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function () {
// ✅ Hide preloader after AJAX completes
f7App.dialog.close();
}
});
});
});

// Page: Customer
$(document).on('page:init', '.page[data-name="customer"]', function () {
// 👇 Ensure Bootstrap re-binds modal events
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
var sendCode = function(code)
{
$('.scan').prop('disabled', true);
$('.manually').prop('disabled', true);
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ code +' sent to boxoffice, plase wait…');

$.ajax({
url: `${ApiUrl}scan`,
method: 'POST',
data: {
token: TOKEN,
event_date_id: eventDateId,
order_code: code
},
success: function(result,status,xhr)
{
var apiResult = JSON.parse(result);

if ( apiResult.result )
{
$('#scan-result').removeClass('bg-dark').addClass('bg-success').html(apiResult.message+''+apiResult.seating+''+apiResult.tickets);

// reset input to set next code
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html(apiResult.message);
}
},
error: function(xhr,status,error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ result.text +' could not be sent to boxoffice, please try again');
},
complete: function()
{
$('.scan').prop('disabled', false);
$('.manually').prop('disabled', false);
}
});
}

var scanError = function (error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html("Scanning failed: " + error);

f7App.popup.open('#modal-scan-result');
};

var scanSuccess = function(result)
{
if (! result.cancelled )
{
if (eventDateId > -1)
{
sendCode(result.text);
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('You must select an event date to scan tickets');
}
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Scan was cancelled');
}

f7App.popup.open('#modal-scan-result');
};
$(document).on('click', '.reload-events', function()
{

f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {

$('.customer-screen ul.events').html('');

const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
// $('.customer-screen ul.events').append(`
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}
//
//
// `);
$('.customer-screen div.events').append(`

${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}

0/500

`);
// $('.customer-screen ul.events').append(`
//
//
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
// ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} –
// ${val.venue_title} – ${val.venue_full}
//
//
//
//
// `);
// $('.customer-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}`);

});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.'+xhr.statusText+xhr.status, 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});

// load events click
$('.reload-events').trigger('click');

$(document).on('click', '.customer-screen .events .list-group-item', function()
{

$('.customer-screen .events .list-group-item').removeClass('active');
$(this).addClass('active');

$('#scan-info').html($(this).html());

eventId = $(this).attr('data-event-id');
eventDateId = $(this).attr('data-event-date-id');

$('[name="code"]').val(eventId +'.'+ eventDateId +'.');

// first scan on event date click
//cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
f7App.popup.open('#modal-scan-result');

});

$(document).on('click', '.scan', function()
{
cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
});

$(document).on('click', '.manually', function()
{
sendCode($('[name="code"]').val());
});

});

// $('ons-button').on('click', function(e) {
// ons.notification.alert('Button is tapped!');
// })

});

}
this is the code

Assistant
Thanks for the full code. Since the AJAX calls work **in browser** but fail with **status `0` in the APK** after updating the **Android SDK**, the issue is likely related to **WebView security changes in the latest Android versions** (SDK 31+), specifically around **network requests and content security**.

### ✅ Confirmed Root Problem:
Cordova on Android (especially on SDK 30+) has stricter policies on external requests from WebView. Your `status: 0` is a **silent fail**, often due to:

– ❌ Content Security Policy (CSP) blocks external requests
– ❌ `cordova-plugin-whitelist` not installed or misconfigured
– ❌ Mixed content (HTTPS app trying HTTP API)
– ❌ New SDK blocking external domains unless explicitly allowed

### ✅ SOLUTION CHECKLIST (Step-by-Step)

#### ✅ 1. Make sure `cordova-plugin-whitelist` is installed
Run:

cordova plugin add cordova-plugin-whitelist

#### ✅ 2. In `config.xml`, add these:

<!-- Allow all network access -->
<access origin="*" />
<allow-navigation href="*" />
<allow-intent href="*" />
<preference name="AndroidLaunchMode" value="singleTask" />

If your API is `https://staging.fossettscircus.com`, you can also do:

<access origin="https://staging.fossettscircus.com" />

#### ✅ 3. Add a **Content Security Policy** meta tag in `index.html`:

<meta http-equiv="Content-Security-Policy" content="default-src * 'self' data: gap: https://staging.fossettscircus.com 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline'; media-src *">

This is crucial or WebView will silently block your AJAX requests.

#### ✅ 4. Debug using `adb logcat`

Run this while testing the app:

adb logcat | grep chromium

This shows errors like:

– `Blocked by Content Security Policy`
– `Mixed content blocked`
– `Failed to load resource`

#### ✅ 5. Verify Permissions & Internet Access

Make sure `AndroidManifest.xml` has:

<uses-permission android:name="android.permission.INTERNET" />

Without this, no network calls will work on real device.

#### ✅ 6. Check for HTTPS issues

If your backend uses a **self-signed certificate** or invalid SSL, WebView **will block** the request.

– Open `https://staging.fossettscircus.com/boxoffice/index.php/api/today` on a mobile browser.
– If there's a certificate error, fix your SSL cert.
– You **cannot bypass SSL warnings in Cordova WebView** without insecure plugins (not recommended).

### 💡 Extra: Force Older SDK (For Testing)

If the issue started after SDK update, try forcing Cordova to use SDK 30:

In `config.xml`:

<preference name="android-targetSdkVersion" value="30" />

Then:

cordova platform rm android
cordova platform add android@latest
cordova build android

### ✅ Summary Fix Guide

| Step | Fix |
|——|—–|
| ✅ Whitelist plugin | `cordova-plugin-whitelist` |
| ✅ CSP tag | Add correct meta tag in `index.html` |
| ✅ config.xml | Allow `access` and `navigation` |
| ✅ Check HTTPS | Confirm backend cert is valid |
| ✅ logcat | Use `adb logcat` to get real cause |

Let me know:
– What SDK version your app is using now?
– If you want me to validate your actual backend endpoint headers?
– If you'd like a pre-built CSP “ and `config.xml` snippet customized for your app.

I'm here to help you get this resolved quickly.

User
Fossettscircus Scanner

Thenet

Assistant
Thank you for sharing your `config.xml`.

You're **almost fully set up**, but a few **critical fixes are missing** that are likely causing your **Cordova Android AJAX requests to fail with status 0** (especially on SDK 30+ or newer WebView versions).

### ✅ You Need to Do These 4 Fixes:

### ✅ 1. Add the Correct “ to `index.html`

In your `www/index.html`, inside “, add:

<meta http-equiv="Content-Security-Policy" content="default-src * 'self' data: gap: https://staging.fossettscircus.com 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline'; media-src *">

Without this, Android's WebView will silently block your `$.ajax()` request — even if you allow everything in `config.xml`.

### ✅ 2. Declare `networkSecurityConfig` for HTTPS and SDK 30+

Create a file: `platforms/android/app/src/main/res/xml/network_security_config.xml`

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config cleartextTrafficPermitted="true">
    <trust-anchors>
      <certificates src="system" />
    </trust-anchors>
  </base-config>
</network-security-config>

Then in `platforms/android/app/src/main/AndroidManifest.xml`, inside the “ tag:

android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"

> This is necessary if you're debugging against HTTP or using an SSL certificate that may not be recognized (e.g., staging/self-signed).

### ✅ 3. Add Android-specific preferences in `config.xml`

Inside your “ tag (root), add:

<preference name="AndroidXEnabled" value="true" />
<preference name="AndroidInsecureFileModeEnabled" value="true" />
<preference name="android-minSdkVersion" value="22" />
<preference name="android-targetSdkVersion" value="30" />

Adjust `targetSdkVersion` if needed. SDK 31+ can cause issues if your app or plugins aren’t fully compatible.

### ✅ 4. Double-Check the `cordova-plugin-whitelist`

Make sure this plugin is **installed**:

cordova plugin add cordova-plugin-whitelist

You’ve added the “ and “ — but **without the plugin, those tags won’t do anything**.

### 🔁 OPTIONAL: Clean + Rebuild

After these changes, **remove and re-add the Android platform** to ensure clean rebuild:

cordova platform rm android
cordova platform add android
cordova build android

### ✅ Final Checklist Summary:

| 🔧 Fix | Status |
|——-|——–|
| ✅ `cordova-plugin-whitelist` | Required ✔️ |
| ✅ CSP meta in `index.html` | Add ✔️ |
| ✅ `network_security_config.xml` | Add ✔️ |
| ✅ `usesCleartextTraffic` & `networkSecurityConfig` in Manifest | Add ✔️ |
| ✅ SDK Targeting and AndroidX | Add ✔️ |

Once these are added, **Cordova will no longer block your AJAX to `https://staging.fossettscircus.com`**, and your customer/staff event list will load as expected.

Let me know if you want me to generate the exact files (`AndroidManifest.xml`, `network_security_config.xml`) or validate SSL from your endpoint!

User
cordova-plugin-android-permissions 1.1.5 "Permissions"
cordova-plugin-battery-status 1.2.5 "Battery"
cordova-plugin-camera 8.0.0 "Camera"
cordova-plugin-device 1.1.7 "Device"
cordova-plugin-dialogs 1.3.4 "Notification"
cordova-plugin-file 8.1.3 "File"
cordova-plugin-geolocation 5.0.0 "Geolocation"
cordova-plugin-globalization 1.0.9 "Globalization"
cordova-plugin-inappbrowser 1.7.2 "InAppBrowser"
cordova-plugin-media-capture 6.0.0 "Capture"
cordova-plugin-network-information 1.3.4 "Network Information"
cordova-plugin-splashscreen 6.0.1 "Splashscreen"
cordova-plugin-vibration 2.1.6 "Vibration"
phonegap-plugin-barcodescanner 8.1.0 "BarcodeScanner"
Assistant
Thanks for listing your plugins — your Cordova setup is solid, **but you are missing the most crucial plugin** that directly affects your AJAX issue on Android:

### ❗ Missing Plugin: `cordova-plugin-whitelist`

This plugin **must be installed** for the “ and AJAX calls to work on Android WebView. Without it, network requests will silently fail — which is exactly what you're experiencing (`status = 0`).

### ✅ To Fix This:

Run:

cordova plugin add cordova-plugin-whitelist

Then confirm it’s added by running:

cordova plugin ls

You should see:

cordova-plugin-whitelist 1.3.5 "Whitelist"

### 🔁 After Installing:

1. Make sure your `config.xml` contains:

<access origin="*" />
<allow-navigation href="*" />
<allow-intent href="*" />

2. Rebuild the Android app:

cordova platform rm android
cordova platform add android
cordova build android

### ✅ Bonus: Test Network from Cordova App

You can confirm it’s working by adding this test in `deviceready`:

fetch('https://staging.fossettscircus.com/boxoffice/index.php/api/today', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: 'token=fossettscircustoken'
})
.then(res => res.text())
.then(res => console.log('✅ Success:', res))
.catch(err => console.error('❌ Fetch Error:', err));

If this still fails **after adding the whitelist plugin**, then the issue is likely in your **CSP** or **Android WebView config**.

Let me know once you add `cordova-plugin-whitelist` — I’ll help you verify and confirm everything is working.

User
admin1@PC-274:~/nethues-projects/Klassenergy-project/android-apps/circusscanner$ cordova build android
Checking Java JDK and Android SDK versions
ANDROID_HOME=/home/admin1/Android/Sdk (recommended setting)
ANDROID_SDK_ROOT=undefined (DEPRECATED)
Using Android SDK: /home/admin1/Android/Sdk

BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
Subproject Path: CordovaLib
Subproject Path: app

> Configure project :app
WARNING: Using flatDir should be avoided because it doesn't support any meta-data formats.

> Task :CordovaLib:compileDebugJavaWithJavac
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :app:compileDebugJavaWithJavac FAILED
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:25: error: cannot find symbol
import org.apache.cordova.Whitelist;
^
symbol: class Whitelist
location: package org.apache.cordova
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:32: error: cannot find symbol
private Whitelist allowedNavigations;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:33: error: cannot find symbol
private Whitelist allowedIntents;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:34: error: cannot find symbol
private Whitelist allowedRequests;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:138: error: cannot find symbol
public Whitelist getAllowedNavigations() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:142: error: cannot find symbol
public void setAllowedNavigations(Whitelist allowedNavigations) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:146: error: cannot find symbol
public Whitelist getAllowedIntents() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:150: error: cannot find symbol
public void setAllowedIntents(Whitelist allowedIntents) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:154: error: cannot find symbol
public Whitelist getAllowedRequests() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:158: error: cannot find symbol
public void setAllowedRequests(Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:50: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:61: error: cannot find symbol
allowedNavigations = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:62: error: cannot find symbol
allowedIntents = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:63: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
21 errors

[Incubating] Problems report is available at: file:///home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/build/reports/problems/problems-report.html

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler output below.
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:25: error: cannot find symbol
import org.apache.cordova.Whitelist;
^
symbol: class Whitelist
location: package org.apache.cordova
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:32: error: cannot find symbol
private Whitelist allowedNavigations;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:33: error: cannot find symbol
private Whitelist allowedIntents;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:34: error: cannot find symbol
private Whitelist allowedRequests;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:138: error: cannot find symbol
public Whitelist getAllowedNavigations() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:142: error: cannot find symbol
public void setAllowedNavigations(Whitelist allowedNavigations) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:146: error: cannot find symbol
public Whitelist getAllowedIntents() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:150: error: cannot find symbol
public void setAllowedIntents(Whitelist allowedIntents) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:154: error: cannot find symbol
public Whitelist getAllowedRequests() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:158: error: cannot find symbol
public void setAllowedRequests(Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:50: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:61: error: cannot find symbol
allowedNavigations = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:62: error: cannot find symbol
allowedIntents = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:63: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
21 errors

* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with –scan to get full insights.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '–warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.13/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD FAILED in 9s
31 actionable tasks: 31 executed
Command failed with exit code 1: /home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/tools/gradlew cdvBuildDebug

Assistant
Thanks for providing the full error log. The issue is **very clear now**:

## ❌ Problem:
You're using the `cordova-plugin-whitelist`, but it's **failing to compile** because:

error: cannot find symbol class Whitelist

> This means that the `Whitelist.java` class from Cordova core **no longer exists** in newer versions (Cordova Android 11+).

This is a **known issue** caused by:
– Adding `cordova-plugin-whitelist` on a Cordova project that uses **modern Android platform (cordova-android 11+)**
– The whitelist logic is now **built-in**, and **you no longer need this plugin**

## ✅ Solution: Remove the plugin (no longer required)

You should **remove the `cordova-plugin-whitelist`** completely and just configure permissions via `config.xml`.

### 🧹 Run this:

cordova plugin rm cordova-plugin-whitelist

Then **verify it's gone**:

cordova plugin ls

## ✅ Then Rebuild:

cordova platform rm android
cordova platform add android@latest
cordova build android

This will remove the incompatible references to the missing `Whitelist` class and clean your Android build.

## ✅ You STILL Need CSP + Access Rules

Even though the plugin is removed, **you must keep the config.xml and CSP setup** like this:

### ✅ In `config.xml`

<access origin="*" />
<allow-navigation href="*" />
<allow-intent href="*" />

### ✅ In `index.html` “

<meta http-equiv="Content-Security-Policy" content="default-src * 'self' data: gap: https://staging.fossettscircus.com 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline'; media-src *">

## ✅ Summary of Actions

| Step | Action |
|——|——–|
| 🔧 1 | Remove `cordova-plugin-whitelist` (not needed in cordova-android 11+) |
| 🔧 2 | Use “ and CSP rules instead |
| 🔧 3 | Clean platform and rebuild |
| 🔧 4 | Keep CSP + allow-navigation in place |

Let me know if you'd like me to review your full `index.html` head or generate a minimal working setup. Once rebuilt, your AJAX calls from Cordova should start working normally on Android again.

User
show error in android studion for emulator device
Assistant
To **show AJAX or JavaScript errors from your Cordova app running on an Android Studio emulator**, follow one of the methods below depending on your setup:

## ✅ Option 1: Use `chrome://inspect` (Best for Cordova/WebView debugging)

### 📱 Steps:

1. **Run your Cordova app** on the emulator using:

cordova run android --emulator

2. **Open Google Chrome** on your PC.

3. In the address bar, go to:

chrome://inspect

4. Under **Remote Target**, your emulator's WebView will show up (e.g., `com.fossettscircus.scanner`).

5. Click **“inspect”** — DevTools will open.

6. Now you can:
– See **console.log** output
– See **network requests** (your AJAX calls)
– View **errors and exceptions**
– Debug your app just like a webpage

> 💡 If you don’t see anything, make sure **Developer options > USB Debugging** is enabled in the emulator.

## ✅ Option 2: Use `adb logcat` for full device logs

1. Open Terminal or Android Studio **Terminal tab**.

2. Run:

adb logcat | grep chromium

or to see general logs:

adb logcat

3. Look for logs like:

I/chromium: [INFO:CONSOLE(12)] "Something went wrong", source: ...

This helps track:
– AJAX errors
– Mixed content issues
– CORS policy violations
– JavaScript syntax problems

## ✅ Option 3: Log Directly in App

Use `console.log` and `alert` during development:

error: function(xhr, status, error) {
  console.log("AJAX failed:", xhr, status, error);
  alert("Error: " + xhr.status + " " + error);
}

### 🔁 Pro Tip (Optional): Enable Full WebView Debugging in Cordova

If not already done, in `config.xml` add:

<preference name="WebViewBounce" value="false" />
<preference name="AndroidWebViewDebuggingEnabled" value="true" />

Let me know if you're using a **physical device** instead — steps are slightly different.

User
document.addEventListener('deviceready', function () {
if (cordova.platformId === 'android') {
var permissions = cordova.plugins.permissions;

permissions.checkPermission(permissions.CAMERA, function (status) {
if (!status.hasPermission) {
// Request permission
permissions.requestPermission(
permissions.CAMERA,
function (status) {
if (status.hasPermission) {
navigator.splashscreen.hide(); // Hide splash after permission
initializeApp(); // Proceed with your app
} else {
navigator.app.exitApp(); // Exit if denied
}
},
function () {
navigator.app.exitApp(); // Exit on request error
}
);
} else {
navigator.splashscreen.hide();
initializeApp(); // Permission already granted
}
});
} else {
navigator.splashscreen.hide(); // For browser/iOS fallback
let TOKEN = 'fossettscircustoken';
var eventId = -1;
var eventDateId = -1;
let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';

var scanConfig = {
preferFrontCamera : false, // iOS and Android
showFlipCameraButton : true, // iOS and Android
showTorchButton : true, // iOS and Android
torchOn: false, // Android, launch with the torch switched on (if available)
saveHistory: false, // Android, save scan history (default false)
prompt : "Place a code inside the scan area", // Android
resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
formats : "QR_CODE", // default: all but PDF_417 and RSS_EXPANDED
//orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device
disableAnimations : true, // iOS
disableSuccessBeep: false // iOS and Android
};
$(document).ready(function()
{
$(document).on('page:init', '.page[data-name="home"]', function () {

});
$(document).on('page:init', function () {
$(document).on('click', '.logout-staff', function()
{

localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});

$(document).on('page:init', '.page[data-name="staff-pay-terminal"]', function () {

$(document).on('input', '#amountInput', function () {
const amount = parseFloat($(this).val());
const btn = $('#chargeBtn');

if (amount > 0) {
btn.removeClass('disabled color-gray').addClass('color-green');
btn.text('Charge €' + amount.toFixed(2));
} else {
btn.addClass('disabled color-gray').removeClass('color-green');
btn.text('Charge €0.00');
}
});
})
var staffEventsLoaded = false;
$(document).on('page:init', '.page[data-name="staff-tickets"]', function () {

$(document).on('click', '.reload-events-staff', function()
{

f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {

$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`

${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}

0/500

`);

//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});

// load events click

$('.reload-events-staff').trigger('click');

});
$(document).on('page:init', '.page[data-name="staff-check-orders"]', function () {

});
$(document).on('page:init', '.page[data-name="staff-dashboard"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-tickets').on('click', function () {
f7App.views.main.router.navigate('/staff-tickets/');
});
$('#open-pay-terminal').on('click', function () {
f7App.views.main.router.navigate('/staff-pay-terminal/');
});
$('#check-orders').on('click', function () {
f7App.views.main.router.navigate('/staff-check-orders/');
});

// load events click
$('.reload-events-staff').trigger('click');

});
$(document).on('page:init', '.page[data-name="staff-login"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-login-form').on('submit', function (e) {
e.preventDefault();
var email = $('#staff-email').val();
var password = $('#staff-password').val();
f7App.dialog.preloader('Logging in…');
$.ajax({
url: `${ApiUrl}staff_login`,
method: 'POST',
data: {
token: TOKEN,
email: email,
password: password
},
success: function (result, status, xhr) {
var apiResult = JSON.parse(result);
if (apiResult.result) {
f7App.views.main.router.navigate('/staff/');
} else {
$('#login-result').html(apiResult.message);
}
},
error: function (xhr, status, error) {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function () {
// ✅ Hide preloader after AJAX completes
f7App.dialog.close();
}
});
});
});

// Page: Customer
$(document).on('page:init', '.page[data-name="customer"]', function () {
// 👇 Ensure Bootstrap re-binds modal events

var sendCode = function(code)
{
$('.scan').prop('disabled', true);
$('.manually').prop('disabled', true);
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ code +' sent to boxoffice, plase wait…');

$.ajax({
url: `${ApiUrl}scan`,
method: 'POST',
data: {
token: TOKEN,
event_date_id: eventDateId,
order_code: code
},
success: function(result,status,xhr)
{
var apiResult = JSON.parse(result);

if ( apiResult.result )
{
$('#scan-result').removeClass('bg-dark').addClass('bg-success').html(apiResult.message+''+apiResult.seating+''+apiResult.tickets);

// reset input to set next code
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html(apiResult.message);
}
},
error: function(xhr,status,error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ result.text +' could not be sent to boxoffice, please try again');
},
complete: function()
{
$('.scan').prop('disabled', false);
$('.manually').prop('disabled', false);
}
});
}

var scanError = function (error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html("Scanning failed: " + error);

f7App.popup.open('#modal-scan-result');
};

var scanSuccess = function(result)
{
if (! result.cancelled )
{
if (eventDateId > -1)
{
sendCode(result.text);
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('You must select an event date to scan tickets');
}
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Scan was cancelled');
}

f7App.popup.open('#modal-scan-result');
};
loadEvent(ApiUrl);
$(document).on('click', '.reload-events', function()
{
loadEvent(ApiUrl);

});

// load events click
//$('.reload-events').trigger('click');

$(document).on('click', '.customer-screen .events .list-group-item', function()
{

$('.customer-screen .events .list-group-item').removeClass('active');
$(this).addClass('active');

$('#scan-info').html($(this).html());

eventId = $(this).attr('data-event-id');
eventDateId = $(this).attr('data-event-date-id');

$('[name="code"]').val(eventId +'.'+ eventDateId +'.');

// first scan on event date click
//cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
f7App.popup.open('#modal-scan-result');

});

$(document).on('click', '.scan', function()
{
cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
});

$(document).on('click', '.manually', function()
{
sendCode($('[name="code"]').val());
});

});

// $('ons-button').on('click', function(e) {
// ons.notification.alert('Button is tapped!');
// })

});

}
}, false);
function loadEvent(ApiUrl)
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {

$('.customer-screen ul.events').html('');

const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
// $('.customer-screen ul.events').append(`
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}
//
//
// `);
$('.customer-screen div.events').append(`

${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}

0/500

`);
// $('.customer-screen ul.events').append(`
//
//
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
// ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} –
// ${val.venue_title} – ${val.venue_full}
//
//
//
//
// `);
// $('.customer-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}`);

});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.'+xhr.statusText+xhr.status, 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
}

loadEvent call not working in android

Assistant
Thanks for the full context. The issue is clear now:

> ❌ Your `loadEvent(ApiUrl)` function **is not working on Android**, but works in the browser. This happens because `TOKEN` is undefined in that context.

## ✅ Root Cause

Inside your `deviceready` block, you declared `TOKEN` like this:

let TOKEN = 'fossettscircustoken';

But your `loadEvent(ApiUrl)` function is **defined outside** that block.

So in Android builds (strict JavaScript scope), `TOKEN` is **not accessible globally**, and becomes **`undefined` inside `loadEvent()`**, which leads to:

– A broken AJAX request
– Possibly a `status: 0` error or blank response
– The request not being sent at all

## ✅ Fix It – Move or Redefine `TOKEN` at the Right Scope

### ✅ Option 1: Move `loadEvent` *inside* `deviceready`

**Preferred for clarity:**

Move this function just **before the line**:

$(document).on('page:init', '.page[data-name="customer"]', function () {

So it shares the same scope as your `TOKEN` and `ApiUrl`.

### ✅ Option 2: Declare TOKEN at the **global level**

Instead of:

let TOKEN = 'fossettscircustoken';

Change it to:

window.TOKEN = 'fossettscircustoken';

Now in `loadEvent()`, `TOKEN` will always be accessible globally.

✅ This is the easiest patch for now.

### ✅ Also: Check Chrome Debug or Log Output

If you're running in Android Emulator or Device, use:

adb logcat | grep chromium

Or open `chrome://inspect` in Chrome to see WebView console.

You might find:

Uncaught ReferenceError: TOKEN is not defined

### ✅ Confirm with a Simple Alert (for testing)

Add this to the first line of `loadEvent()`:

alert("TOKEN: " + TOKEN); // will show undefined if broken

If alert says `undefined`, then that proves the scope issue.

## ✅ Summary

| Issue | Fix |
|——-|—–|
| `TOKEN` undefined inside `loadEvent()` | Make it global or move function inside `deviceready` |
| Scope mismatch | Don't use `let TOKEN` inside isolated blocks unless shared scope |
| Silent AJAX failure in Android | Caused by `undefined` token, not network |

Let me know if you want a full restructured version of the file with corrected scope and refactored flow.

Leave a Comment

Your email address will not be published. Required fields are marked *