{"id":91623,"date":"2026-07-26T19:36:00","date_gmt":"2026-07-26T12:36:00","guid":{"rendered":"https:\/\/careerhub.huflit.edu.vn\/schedule-hiw26-interview\/"},"modified":"2026-09-04T09:19:17","modified_gmt":"2026-09-04T02:19:17","slug":"schedule-hiw26-interview","status":"publish","type":"page","link":"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/","title":{"rendered":"Schedule HIW26 Interview"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"91623\" class=\"elementor elementor-91623 elementor-84554\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b637c13 e-flex e-con-boxed e-con e-parent\" data-id=\"b637c13\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-766bd37 elementor-widget__width-initial elementor-widget elementor-widget-html\" data-id=\"766bd37\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- ======================================================== -->\n<!-- HTML CODE FOR WORDPRESS (INTERVIEWER PORTAL V2.1)     -->\n<!-- ======================================================== -->\n\n<div id=\"hiw26-employer-root\"><\/div>\n\n<style>\n  @import url('https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&display=swap');\n\n  #hiw26-employer-root {\n    font-family: 'Inter', sans-serif;\n    color: #333;\n    min-height: 80vh;\n    padding: 20px;\n    background-color: #f8fafc;\n    border-radius: 12px;\n  }\n\n  .emp-card {\n    background: white;\n    border-radius: 16px;\n    padding: 32px;\n    width: 100%;\n    max-width: 100%;\n    margin: 0 auto;\n    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05);\n  }\n\n  .emp-title {\n    font-size: 24px;\n    font-weight: 700;\n    color: #0f172a;\n    margin-bottom: 8px;\n  }\n\n  .emp-input {\n    width: 100%;\n    padding: 12px 16px;\n    border: 1px solid #cbd5e1;\n    border-radius: 8px;\n    font-size: 16px;\n    margin-bottom: 16px;\n  }\n\n  .emp-btn {\n    width: 100%;\n    padding: 14px;\n    background: #0f52fb;\n    border: none;\n    border-radius: 8px;\n    color: white;\n    font-weight: 600;\n    font-size: 16px;\n    cursor: pointer;\n  }\n\n  .emp-btn:hover {\n    background: #ec6523;\n  }\n\n  \/* Tabs Styles *\/\n  .nav-tabs {\n    display: flex;\n    border-bottom: 2px solid #e2e8f0;\n    margin-bottom: 20px;\n  }\n\n  .tab-btn {\n    padding: 12px 24px;\n    background: none;\n    border: none;\n    font-size: 16px;\n    font-weight: 600;\n    color: #64748b;\n    cursor: pointer;\n    border-bottom: 2px solid transparent;\n    margin-bottom: -2px;\n  }\n\n  .tab-btn.active {\n    color: #0f52fb;\n    border-bottom: 2px solid #0f52fb;\n  }\n\n  .tab-content {\n    display: none;\n  }\n\n  .tab-content.active {\n    display: block;\n  }\n\n  \/* Table Styles (Tab 1) *\/\n  .table-wrapper {\n    overflow-x: auto;\n  }\n\n  table {\n    width: 100%;\n    border-collapse: collapse;\n  }\n\n  th,\n  td {\n    padding: 12px;\n    text-align: left;\n    border-bottom: 1px solid #e2e8f0;\n    font-size: 14px;\n  }\n\n  th {\n    background: #f8fafc;\n    font-weight: 600;\n    color: #475569;\n  }\n\n  \/* Date Time Inputs *\/\n  .dt-input {\n    padding: 6px;\n    border: 1px solid #cbd5e1;\n    border-radius: 4px;\n    font-size: 13px;\n    margin-right: 4px;\n  }\n\n  .btn-schedule {\n    padding: 6px 12px;\n    background: #0f52fb;\n    color: white;\n    border: none;\n    border-radius: 4px;\n    cursor: pointer;\n    font-size: 13px;\n    font-weight: 600;\n  }\n\n  .btn-schedule:hover {\n    background: #0f52fb;\n  }\n\n  \/* Accordion Styles (Tab 2) *\/\n  .shift-group {\n    margin-bottom: 16px;\n    border: 1px solid #e2e8f0;\n    border-radius: 8px;\n    overflow: hidden;\n  }\n\n  .shift-header {\n    background: #f1f5f9;\n    padding: 16px;\n    font-weight: 600;\n    font-size: 16px;\n    color: #0f172a;\n    cursor: pointer;\n    display: flex;\n    justify-content: space-between;\n  }\n\n  .shift-header:hover {\n    background: #e2e8f0;\n  }\n\n  .shift-body {\n    padding: 16px;\n    background: white;\n    display: block;\n  }\n\n  \/* Candidate Item *\/\n  .candidate-item {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 16px;\n    border: 1px solid #e2e8f0;\n    border-radius: 8px;\n    margin-bottom: 12px;\n    background: #f8fafc;\n  }\n\n  .candidate-item.active {\n    border-color: #10b981;\n    background: #ecfdf5;\n  }\n\n  .c-info h4 {\n    margin: 0 0 4px 0;\n    font-size: 16px;\n    color: #0f172a;\n  }\n\n  .c-info p {\n    margin: 0;\n    font-size: 14px;\n    color: #64748b;\n  }\n\n  .action-btn {\n    padding: 8px 16px;\n    border: none;\n    border-radius: 6px;\n    font-weight: 600;\n    cursor: pointer;\n  }\n\n  .btn-call {\n    background: #10b981;\n    color: white;\n  }\n\n  .btn-done {\n    background: #64748b;\n    color: white;\n  }\n\n  .badge {\n    padding: 4px 8px;\n    border-radius: 20px;\n    font-size: 12px;\n    font-weight: 600;\n  }\n\n  .b-green {\n    background: #dcfce3;\n    color: #166534;\n  }\n\n  .b-yellow {\n    background: #fef3c7;\n    color: #92400e;\n  }\n\n  .b-gray {\n    background: #f1f5f9;\n    color: #475569;\n  }\n\n  .b-red {\n    background: #fee2e2;\n    color: #991b1b;\n  }\n\n  .b-orange {\n    background: #ffedd5;\n    color: #9a3412;\n  }\n\n  \/* Modal Styles *\/\n  .modal-overlay {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background: rgba(0, 0, 0, 0.6);\n    display: none;\n    justify-content: center;\n    align-items: center;\n    z-index: 1000;\n  }\n\n  .modal-content {\n    background: white;\n    padding: 24px;\n    border-radius: 12px;\n    width: 90%;\n    max-width: 500px;\n    max-height: 80vh;\n    overflow-y: auto;\n    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n  }\n\n  .modal-close {\n    float: right;\n    cursor: pointer;\n    font-size: 24px;\n    color: #64748b;\n    line-height: 1;\n  }\n<\/style>\n\n<script>\n  \/\/ URL C\u1ee6A GOOGLE APPS SCRIPT\n  const SCRIPT_URL = \"https:\/\/script.google.com\/macros\/s\/AKfycbxwn1bNWQifwbmJgEnz2c0vlk52PjzYWXFcWPV-f_DQcV-wSDie9OIqdV3CKD71oc7-\/exec\";\n\n  let employerData = [];\n  let filteredData = [];\n  let currentEmployerId = \"\";\n  let globalShiftsData = {};\n  let currentActiveTab = 1;\n  let isUpdating = false;\n  let lastUpdateTime = 0;\n\n  let currentPage = 1;\n  const itemsPerPage = 20;\n\n  function renderEmpLogin() {\n    const root = document.getElementById(\"hiw26-employer-root\");\n    root.innerHTML = `\n    <div class=\"emp-card\" style=\"max-width: 800px; text-align: center;\">\n      <h1 class=\"emp-title\">HUFLIT Internship Week 2026 Interview Scheduling Portal<br\/>For Employers<\/h1>\n      <p style=\"font-weight: bold; color: #ea580c; text-align: center; line-height: 1.5; font-size: 14px; margin-bottom: 24px;\">\n        Dear employers, please enter the Company ID provided by the Organizing Committee in the user guide email.\n      <\/p>\n      <input type=\"text\" id=\"employerInput\" class=\"emp-input\" placeholder=\"Enter Company ID (e.g., 9317)...\" \/>\n      <button class=\"emp-btn\" onclick=\"empLogin()\">Enter Management Room<\/button>\n    <\/div>\n  `;\n  }\n\n  async function empLogin() {\n    const empId = document.getElementById(\"employerInput\").value.trim();\n    if (!empId) {\n      await hiwAlert(\"Please enter the Company ID\");\n      return;\n    }\n\n    currentEmployerId = empId;\n    const btn = document.querySelector('.emp-btn');\n    btn.innerText = \"Loading data...\";\n\n    try {\n      const res = await fetch(`${SCRIPT_URL}?action=get_employer_data&employerId=${empId}`);\n      const result = await res.json();\n      if (result.success) {\n        \/\/ L\u1ecdc c\u00e1c \u1ee9ng vi\u00ean \u0111\u01b0\u1ee3c \"approved\"\n        employerData = result.data.filter(c => {\n          const s = String(c.cvStatus || '').toLowerCase().trim();\n          return s === \"approved\" || s === \"\u0111\u00e3 duy\u1ec7t\" || s === \"\u0111\u00e3 x\u00e1c nh\u1eadn\";\n        });\n\n        if (employerData.length > 0) {\n          renderEmpDashboard();\n          startEmpPolling();\n        } else {\n          await hiwAlert(\"No candidates found for this Company ID, or no candidates have been approved yet.\");\n          btn.innerText = \"Enter Management Room\";\n        }\n      }\n    } catch (e) {\n      await hiwAlert(\"Network connection error.\");\n    }\n  }\n\n  let empPollingInterval = null;\n\n  function startEmpPolling() {\n    if (empPollingInterval) clearInterval(empPollingInterval);\n    empPollingInterval = setInterval(async () => {\n      \/\/ T\u1ea1m d\u1eebng polling n\u1ebfu \u0111ang c\u1eadp nh\u1eadt HO\u1eb6C v\u1eeba m\u1edbi c\u1eadp nh\u1eadt trong v\u00f2ng 20 gi\u00e2y (\u0111\u1ec3 ch\u1edd Google Sheet x\u1eed l\u00fd xong)\n      if (!currentEmployerId || isUpdating || (Date.now() - lastUpdateTime < 20000)) return;\n      try {\n        const res = await fetch(`${SCRIPT_URL}?action=get_employer_data&employerId=${currentEmployerId}`);\n        const result = await res.json();\n        if (result.success && !isUpdating) {\n          employerData = result.data.filter(c => {\n            const s = String(c.cvStatus || '').toLowerCase().trim();\n            return s === \"approved\" || s === \"\u0111\u00e3 duy\u1ec7t\" || s === \"\u0111\u00e3 x\u00e1c nh\u1eadn\";\n          });\n\n          const activeElement = document.activeElement;\n          const isInputFocused = activeElement && ['INPUT', 'SELECT', 'TEXTAREA'].includes(activeElement.tagName);\n          const modalNode = document.getElementById('emailPreviewModal');\n          const isModalOpen = modalNode && modalNode.style.display === 'flex';\n\n          if (!isInputFocused && !isModalOpen) {\n            renderEmpDashboard(true);\n          }\n        }\n      } catch (e) {\n        console.error(\"Background update error\", e);\n      }\n    }, 10000);\n  }\n\n  function renderEmpDashboard(keepPage = false) {\n    if (!keepPage) currentPage = 1;\n\n    employerData.sort((a, b) => String(a.time).localeCompare(String(b.time)));\n\n    \/\/ Extract unique job titles\n    const uniqueJobs = [...new Set(employerData.map(c => c.jobTitle).filter(Boolean))];\n    const prevFilter = document.getElementById(\"jobTitleFilter\") ? document.getElementById(\"jobTitleFilter\").value : \"All\";\n\n    filteredData = employerData;\n    if (prevFilter !== \"All\") {\n      filteredData = employerData.filter(c => String(c.jobTitle) === prevFilter);\n    }\n\n    const totalCandidates = employerData.length;\n    const scheduledCandidates = employerData.filter(c => c.time && c.date).length;\n    const unscheduledCandidates = totalCandidates - scheduledCandidates;\n\n    const overviewHtml = `\n      <div style=\"display: flex; gap: 16px; margin-bottom: 20px;\">\n        <div style=\"flex:1; background:#f8fafc; padding: 16px; border-radius: 8px; border: 1px solid #e2e8f0; text-align: center;\">\n          <div style=\"font-size: 13px; color: #64748b; font-weight: 600; text-transform: uppercase;\">Total Candidates<\/div>\n          <div style=\"font-size: 24px; font-weight: 700; color: #0f172a; margin-top: 4px;\">${totalCandidates}<\/div>\n        <\/div>\n        <div style=\"flex:1; background:#f0fdf4; padding: 16px; border-radius: 8px; border: 1px solid #bbf7d0; text-align: center;\">\n          <div style=\"font-size: 13px; color: #166534; font-weight: 600; text-transform: uppercase;\">Scheduled<\/div>\n          <div style=\"font-size: 24px; font-weight: 700; color: #15803d; margin-top: 4px;\">${scheduledCandidates}<\/div>\n        <\/div>\n        <div style=\"flex:1; background:#fff7ed; padding: 16px; border-radius: 8px; border: 1px solid #fed7aa; text-align: center;\">\n          <div style=\"font-size: 13px; color: #9a3412; font-weight: 600; text-transform: uppercase;\">Unscheduled<\/div>\n          <div style=\"font-size: 24px; font-weight: 700; color: #c2410c; margin-top: 4px;\">${unscheduledCandidates}<\/div>\n        <\/div>\n      <\/div>\n    `;\n\n    const root = document.getElementById(\"hiw26-employer-root\");\n    root.innerHTML = `\n    <div class=\"emp-card\">\n      <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;\">\n        <h2 class=\"emp-title\">Employer: ${employerData[0].company}<\/h2>\n        <button onclick=\"renderEmpLogin()\" style=\"padding: 6px 12px; border-radius: 4px; cursor: pointer;\">Log Out<\/button>\n      <\/div>\n\n      ${overviewHtml}\n\n      <div style=\"margin-bottom: 16px; background: #f8fafc; padding: 12px; border: 1px solid #e2e8f0; border-radius: 8px;\">\n         <strong style=\"margin-right: 8px; color: #0f172a; font-size: 14px;\">\ud83d\udd0e Filter candidates:<\/strong>\n         <select id=\"jobTitleFilter\" class=\"emp-input\" style=\"width: auto; padding: 8px; margin: 0;\" onchange=\"renderEmpDashboard()\">\n            <option value=\"All\">--- All positions ---<\/option>\n            ${uniqueJobs.map(job => {\n      const count = employerData.filter(c => String(c.jobTitle) === job).length;\n      return `<option value=\"${job}\" ${job === prevFilter ? 'selected' : ''}>${job} (${count} candidates)<\/option>`;\n    }).join('')}\n         <\/select>\n      <\/div>\n\n      <div class=\"nav-tabs\">\n        <button class=\"tab-btn ${currentActiveTab === 1 ? 'active' : ''}\" onclick=\"switchTab(1)\" id=\"btnTab1\">1. Scheduling & List<\/button>\n        <button class=\"tab-btn ${currentActiveTab === 2 ? 'active' : ''}\" onclick=\"switchTab(2)\" id=\"btnTab2\">2. Shift Coordination<\/button>\n      <\/div>\n\n      <!-- TAB 1: B\u1ea2NG T\u1ed4NG & X\u1ebeP L\u1ecaCH -->\n      <div id=\"tab1\" class=\"tab-content ${currentActiveTab === 1 ? 'active' : ''}\">\n        <div style=\"margin-bottom: 16px; padding: 12px; background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 6px; font-size: 14px;\">\n          \ud83d\udca1 <strong>Instructions:<\/strong> Select the date and time for unscheduled candidates, then click <strong>Schedule<\/strong>. Interview invitation emails will be automatically sent to the candidates.\n        <\/div>\n\n        <!-- BULK SCHEDULING UI (COLLAPSIBLE) -->\n        <details style=\"background: #fff; padding: 16px 20px; border-radius: 12px; border: 2px dashed #0f52fb; margin-bottom: 30px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05); cursor: pointer;\">\n          <summary style=\"font-size: 18px; color: #ec6523; font-weight: 600; list-style: none; display: flex; justify-content: space-between; align-items: center; outline: none;\">\n            <div style=\"display: flex; align-items: center; gap: 8px;\">\n              <span>\u26a1 Automatic Bulk Scheduling<\/span>\n              <span style=\"font-size: 13px; background: #dbeafe; color: #1e3a8a; padding: 4px 10px; border-radius: 12px; font-weight: 600;\">For unscheduled candidates<\/span>\n            <\/div>\n            <span style=\"font-size: 14px; color: #64748b;\">(Click to Open \/ Close) \u25bc<\/span>\n          <\/summary>\n          \n          <div style=\"margin-top: 16px; border-top: 1px dashed #bfdbfe; padding-top: 16px; cursor: default;\" onclick=\"event.stopPropagation()\">\n            <p style=\"font-size: 14px; color: #475569; margin-bottom: 16px;\">The system will automatically allocate consecutive timeslots for <strong>ALL<\/strong> candidates currently displayed in the table below (according to the Position Filter) who have not been scheduled yet.<\/p>\n            <div style=\"display: flex; gap: 12px; align-items: center; flex-wrap: wrap;\">\n              <input type=\"date\" id=\"bulkDate\" class=\"emp-input\" style=\"width: auto; margin-bottom: 0;\">\n              <select id=\"bulkShift\" class=\"emp-input\" style=\"width: auto; margin-bottom: 0;\">\n                <option value=\"08:30\">Morning Shift (08:30 - 11:30)<\/option>\n                <option value=\"13:30\">Afternoon Shift (13:30 - 16:30)<\/option>\n                <option value=\"18:00\">Evening Shift (18:00 - 20:30)<\/option>\n              <\/select>\n              <select id=\"bulkDuration\" class=\"emp-input\" style=\"width: auto; margin-bottom: 0;\">\n                <option value=\"10\">10 mins \/ person<\/option>\n                <option value=\"15\" selected>15 mins \/ person<\/option>\n                <option value=\"20\">20 mins \/ person<\/option>\n              <\/select>\n              <button class=\"emp-btn\" style=\"width: auto; background: #0f52fb; font-weight: bold; border-radius: 8px;\" onclick=\"bulkSchedule()\" id=\"btn-bulk\">Auto Create Schedule & Preview<\/button>\n            <\/div>\n          <\/div>\n        <\/details>\n        <!-- END BULK SCHEDULING -->\n\n        <h3 style=\"font-size: 18px; color: #0f172a; margin-bottom: 16px; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px;\">\ud83d\udccb Manual Scheduling & Candidate List<\/h3>\n        \n        <div class=\"table-wrapper\">\n          <table>\n            <thead>\n              <tr>\n                <th>Candidate ID<\/th>\n                <th>Candidate Information<\/th>\n                <th>Applied Position<\/th>\n                <th>Scheduled Time<\/th>\n                <th>Confirmation<\/th>\n                <th>Interview Check-in Status<\/th>\n                <th>Interview Result<\/th>\n              <\/tr>\n            <\/thead>\n            <tbody>\n              ${renderEmpTableRows(filteredData).html}\n            <\/tbody>\n          <\/table>\n        <\/div>\n        \n        ${renderEmpTableRows(filteredData).paginationHtml}\n        \n      <\/div>\n\n      <!-- TAB 2: \u0110I\u1ec0U PH\u1ed0I THEO CA -->\n      <div id=\"tab2\" class=\"tab-content ${currentActiveTab === 2 ? 'active' : ''}\">\n        <div style=\"margin-bottom: 16px; padding: 12px; background: #fffbeb; border: 1px solid #fde68a; border-radius: 6px; font-size: 14px;\">\n          \ud83d\udca1 Note: Candidates <strong>Not Scheduled<\/strong> will not appear in this Tab. Please schedule them in Tab 1 first.\n        <\/div>\n\n        ${renderShiftsAccordion(filteredData)}\n      <\/div>\n\n      <!-- EMAIL PREVIEW MODAL -->\n      <div id=\"emailPreviewModal\" class=\"modal-overlay\">\n        <div class=\"modal-content\">\n          <div class=\"modal-close\" onclick=\"closeEmailPreview()\">&times;<\/div>\n          <h2 style=\"font-size: 20px; color: #0f172a; margin-top: 0; margin-bottom: 16px;\">\ud83d\udce7 CONFIRM SENDING INVITATION<\/h2>\n          <div id=\"emailPreviewContent\" style=\"background: #f8fafc; padding: 16px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 14px; color: #334155; line-height: 1.6; margin-bottom: 20px; text-align: left;\">\n            <!-- Content gets injected here -->\n          <\/div>\n          <div style=\"display: flex; gap: 12px; justify-content: flex-end;\">\n            <button class=\"emp-btn\" style=\"background: #e2e8f0; color: #475569; width: auto;\" onclick=\"closeEmailPreview()\">Cancel<\/button>\n            <button id=\"btn-confirm-email\" class=\"emp-btn\" style=\"background: #0f52fb; width: auto;\">Send Letter & Schedule<\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n\n    <\/div>\n  `;\n  }\n\n  function openEmailPreview(content, onConfirm) {\n    document.getElementById('emailPreviewModal').style.display = 'flex';\n    document.getElementById('emailPreviewContent').innerHTML = content;\n    document.getElementById('btn-confirm-email').onclick = async () => {\n      document.getElementById('btn-confirm-email').innerText = \"Sending...\";\n      document.getElementById('btn-confirm-email').disabled = true;\n      await onConfirm();\n\n      const modal = document.getElementById('emailPreviewModal');\n      if (modal) modal.style.display = 'none';\n\n      const btn = document.getElementById('btn-confirm-email');\n      if (btn) {\n        btn.innerText = \"Send Letter & Schedule\";\n        btn.disabled = false;\n      }\n    };\n  }\n\n  function closeEmailPreview() {\n    document.getElementById('emailPreviewModal').style.display = 'none';\n  }\n\n  function renderEmpTableRows(filteredData) {\n    const totalItems = filteredData.length;\n    const totalPages = Math.ceil(totalItems \/ itemsPerPage) || 1;\n\n    if (currentPage > totalPages) currentPage = totalPages;\n    if (currentPage < 1) currentPage = 1;\n\n    const startIndex = (currentPage - 1) * itemsPerPage;\n    const paginatedData = filteredData.slice(startIndex, startIndex + itemsPerPage);\n\n    let html = paginatedData.map(c => {\n      let confirmBadge = 'b-yellow';\n      let rowStyle = '';\n      if (c.confirm.includes('\u0110\u00e3')) {\n        confirmBadge = 'b-green';\n      } else if (c.confirm === 'T\u1eeb ch\u1ed1i') {\n        confirmBadge = 'b-red';\n        rowStyle = 'background-color: #fef2f2; border-left: 4px solid #ef4444;';\n      } else if (c.confirm === 'Xin \u0111\u1ed5i gi\u1edd') {\n        confirmBadge = 'b-orange';\n        rowStyle = 'background-color: #fff7ed; border-left: 4px solid #f97316;';\n      }\n\n      let reasonHtml = '';\n      if ((c.confirm === 'T\u1eeb ch\u1ed1i' || c.confirm === 'Xin \u0111\u1ed5i gi\u1edd') && c.reason) {\n        reasonHtml = `<div style=\"color: #ef4444; font-size: 11px; margin-top: 4px;\"><strong>Reason:<\/strong> ${c.reason}<\/div>`;\n      }\n\n      return `\n                <tr style=\"${rowStyle}\">\n                  <td><strong>${c.candidateId}<\/strong><\/td>\n                  <td>\n                     <strong>${c.name}<\/strong><br>\n                     <span style=\"color:#64748b; font-size:12px\">Cohort: ${c.course || \"Unspecified\"}<\/span><br>\n                     <span style=\"color:#64748b; font-size:12px\">${c.phone} | ${c.email}<\/span>\n                  <\/td>\n                  <td><strong>${c.jobTitle || \"Unspecified\"}<\/strong><\/td>\n                  <td>\n                    ${c.time && c.date ?\n          `<strong>${formatTimeDisplay(c.time)}<\/strong><br><span style=\"color:#64748b; font-size:12px\">${formatDateDisplay(c.date)}<\/span>` : ''\n        }\n                    ${c.confirm === 'Xin \u0111\u1ed5i gi\u1edd' ?\n          `<div style=\"margin-top: 8px; padding: 6px; background: #fff7ed; border: 1px dashed #fdba74; border-radius: 4px;\">\n           <div style=\"font-size: 11px; color: #c2410c; font-weight: bold;\">(Go to Tab 2 to reschedule)<\/div>\n         <\/div>` : (!c.time || !c.date ?\n            `<input type=\"date\" id=\"date_tab1_${c.applicationId}\" class=\"dt-input\">\n         <input type=\"time\" id=\"time_tab1_${c.applicationId}\" lang=\"en-GB\" class=\"dt-input\">\n         <button class=\"btn-schedule\" onclick=\"scheduleCandidate('${c.applicationId}', 'tab1_')\">Schedule<\/button>` : '')\n        }\n                  <\/td>\n                  <td><span class=\"badge ${confirmBadge}\">${c.confirm || 'Unscheduled'}<\/span>${reasonHtml}<\/td>\n                  <td><span class=\"badge ${c.status === '\u0110ang ph\u1ecfng v\u1ea5n' ? 'b-green' : (c.status === 'Ho\u00e0n th\u00e0nh' ? 'b-gray' : 'b-yellow')}\">${c.status}<\/span><\/td>\n                  <td><strong style=\"color: ${c.result === '\u0110\u1eadu' ? '#10b981' : (c.result === 'R\u1edbt' ? '#ef4444' : '#64748b')}\">${c.result || \"--\"}<\/strong><\/td>\n                <\/tr>\n        `;\n    }).join('');\n\n    let paginationHtml = `\n          <!-- PAGINATION -->\n          <div style=\"display: flex; justify-content: center; align-items: center; gap: 16px; margin-top: 20px; font-size: 14px;\">\n            <button class=\"emp-btn\" onclick=\"changeEmpPage(-1)\" ${currentPage === 1 ? 'disabled style=\"width:auto; opacity:0.5; cursor:not-allowed; padding:8px 16px;\"' : 'style=\"width:auto; background:white; color:#0f172a; border:1px solid #cbd5e1; padding:8px 16px;\"'}>Previous<\/button>\n            <span>Page <strong>${currentPage}<\/strong> \/ ${totalPages}<\/span>\n            <button class=\"emp-btn\" onclick=\"changeEmpPage(1)\" ${currentPage === totalPages ? 'disabled style=\"width:auto; opacity:0.5; cursor:not-allowed; padding:8px 16px;\"' : 'style=\"width:auto; background:white; color:#0f172a; border:1px solid #cbd5e1; padding:8px 16px;\"'}>Next<\/button>\n          <\/div>\n        `;\n\n    return { html, paginationHtml };\n  }\n\n  function changeEmpPage(step) {\n    currentPage += step;\n    renderEmpDashboard(true);\n  }\n\n  function formatTimeDisplay(timeStr) {\n    if (!timeStr) return \"\";\n    const s = String(timeStr).trim();\n    if (s.includes('1899') || s.includes('T')) {\n      const d = new Date(s);\n      if (!isNaN(d)) return String(d.getHours()).padStart(2, '0') + ':' + String(d.getMinutes()).padStart(2, '0');\n    }\n    const parts = s.split(':');\n    if (parts.length >= 2) {\n      return String(parts[0]).padStart(2, '0') + ':' + String(parts[1]).padStart(2, '0');\n    }\n    return s;\n  }\n\n  function formatDateDisplay(dateStr) {\n    if (!dateStr) return \"\";\n    const s = String(dateStr).trim();\n    let d = new Date(s);\n    if (!isNaN(d) && s.includes('-')) {\n      return String(d.getDate()).padStart(2, '0') + '\/' + String(d.getMonth() + 1).padStart(2, '0') + '\/' + String(d.getFullYear()).slice(-2);\n    }\n    const parts = s.split('\/');\n    if (parts.length >= 2) {\n      let y = parts[2] || new Date().getFullYear().toString();\n      return String(parts[0]).padStart(2, '0') + '\/' + String(parts[1]).padStart(2, '0') + '\/' + String(y).slice(-2);\n    }\n    return s;\n  }\n\n  async function scheduleCandidate(applicationId, prefix = '') {\n    const dateInput = document.getElementById(`date_${prefix}${applicationId}`).value;\n    const timeInput = document.getElementById(`time_${prefix}${applicationId}`).value;\n\n    if (!dateInput || !timeInput) {\n      await hiwAlert(\"Please select both Date and Time to schedule!\");\n      return;\n    }\n\n    const d = new Date(dateInput);\n    const formattedDate = `${String(d.getDate()).padStart(2, '0')}\/${String(d.getMonth() + 1).padStart(2, '0')}\/${String(d.getFullYear()).slice(-2)}`;\n    const c = employerData.find(x => String(x.applicationId) === String(applicationId));\n\n    if (!c) return;\n\n\n    const emailContent = `\n          <strong>Dear candidate ${c.name},<\/strong><br><br>\n          Company <strong>${c.company}<\/strong> cordially invites you to attend an interview for the position you applied for.<br>\n          - <strong>Time:<\/strong> ${timeInput} - Date ${formattedDate}<br>\n          - <strong>Format:<\/strong> Online Interview<br><br>\n          Please log in to the <strong>Student Portal<\/strong> to <strong>Confirm<\/strong> or <strong>Request Reschedule<\/strong>.<br><br>\n          Best regards,<br>\n          <strong>Recruitment Department ${c.company}<\/strong>\n        `;\n\n    openEmailPreview(emailContent, async () => {\n      isUpdating = true;\n\n      c.date = formattedDate;\n      c.time = timeInput;\n      c.confirm = \"Pending confirmation\";\n\n      renderEmpDashboard(); \/\/ UI updates instantly\n\n      try {\n        const res = await fetch(`${SCRIPT_URL}?action=schedule&candidateId=${applicationId}&employerId=${currentEmployerId}&date=${encodeURIComponent(formattedDate)}&time=${encodeURIComponent(timeInput)}`);\n        const result = await res.json();\n        if (result.success) {\n          await hiwAlert(\"Interview scheduled successfully!\");\n        } else {\n          await hiwAlert(\"Server error: \" + (result.error || \"Candidate not found\"));\n          c.date = \"\"; c.time = \"\"; c.confirm = \"\";\n          renderEmpDashboard();\n        }\n      } catch (e) {\n        console.error(\"Update error\", e);\n        await hiwAlert(\"Error connecting to server!\");\n      } finally {\n        lastUpdateTime = Date.now();\n        isUpdating = false;\n      }\n    });\n  }\n\n  \/\/ Logic nh\u00f3m \u1ee9ng vi\u00ean theo Ca\n  function renderShiftsAccordion(filteredData) {\n    const shifts = {};\n\n    \/\/ Ch\u1ec9 l\u1ea5y nh\u1eefng ai \u0111\u00e3 \u0111\u01b0\u1ee3c x\u1ebfp gi\u1edd trong danh s\u00e1ch \u0111\u00e3 l\u1ecdc\n    const scheduledCandidates = filteredData.filter(c => c.time && c.date);\n\n    if (scheduledCandidates.length === 0) {\n      return `<p style=\"text-align:center; padding: 40px; color: #64748b;\">No candidates have been scheduled yet.<\/p>`;\n    }\n    \n    \/\/ T\u1ef1 \u0111\u1ed9ng d\u00f9ng chung Link Zoom cho t\u1ea5t c\u1ea3 c\u00e1c ca (n\u1ebfu c\u00f3 \u00edt nh\u1ea5t 1 b\u1ea1n c\u00f3 link)\n    let globalZoomLink = \"\";\n    const cWithLink = scheduledCandidates.find(c => c.zoomLink && c.zoomLink.trim() !== \"\");\n    if (cWithLink) globalZoomLink = cWithLink.zoomLink;\n\n    scheduledCandidates.forEach(c => {\n      let timeStr = String(c.time);\n      let shiftName = \"Interview Shift\";\n\n      if (timeStr.includes(':')) {\n        let hour = parseInt(timeStr.split(':')[0]);\n        if (!isNaN(hour)) {\n          if (hour < 12) shiftName = `\ud83c\udf1e Morning Shift`;\n          else if (hour < 18) shiftName = `\ud83c\udf07 Afternoon Shift`;\n          else shiftName = `\ud83c\udf19 Evening Shift`;\n        }\n      } else {\n        shiftName = `Shift: ${timeStr}`;\n      }\n\n      let dateStr = formatDateDisplay(c.date);\n      let groupKey = `${dateStr ? 'Date ' + dateStr + ' | ' : ''}${shiftName}`;\n\n      if (!shifts[groupKey]) shifts[groupKey] = [];\n      shifts[groupKey].push(c);\n    });\n\n    let html = '';\n    globalShiftsData = shifts;\n    for (const [shiftName, candidates] of Object.entries(shifts)) {\n      let zoomLink = \"\";\n      const cLocal = candidates.find(c => c.zoomLink && c.zoomLink.trim() !== \"\");\n      if (cLocal) {\n        zoomLink = cLocal.zoomLink;\n      } else {\n        zoomLink = globalZoomLink;\n      }\n      let zoomBtnHtml = `<button onclick=\"${zoomLink ? `window.open('${zoomLink}', '_blank')` : `hiwAlert('The Organizing Committee has not updated the Zoom Link for this interview shift yet!')`}; event.stopPropagation();\" style=\"margin-right: 12px; padding: 4px 10px; background: ${zoomLink ? '#0f52fb' : '#94a3b8'}; color: white; border: none; border-radius: 4px; font-size: 13px; cursor: pointer; display:inline-flex; align-items:center; line-height: 1.2;\"><span style=\"margin-right:4px;\">\ud83c\udfa5<\/span> Enter Interview Room<\/button>`;\n\n      html += `\n      <div class=\"shift-group\">\n        <div class=\"shift-header\" onclick=\"toggleShift(this)\">\n          <span>${shiftName} <span style=\"color:#64748b; font-weight:normal; font-size:14px;\">(${candidates.length} candidates)<\/span><\/span>\n          <div style=\"display:flex; align-items:center;\">\n             ${zoomBtnHtml}\n             <button onclick=\"downloadCSV('${shiftName}'); event.stopPropagation();\" style=\"margin-right: 12px; padding: 4px 10px; background: #10b981; color: white; border: none; border-radius: 4px; font-size: 13px; cursor: pointer;\">\ud83d\udce5 Download List<\/button>\n             <span>\u25bc<\/span>\n          <\/div>\n        <\/div>\n        <div class=\"shift-body\">\n    `;\n\n      candidates.forEach(c => {\n        const isCalling = c.status === \"\u0110ang ph\u1ecfng v\u1ea5n\";\n        let cardStyle = \"\";\n        let confirmColor = \"#f59e0b\"; \/\/ yellow\n        if (c.confirm.includes('\u0110\u00e3')) confirmColor = \"#10b981\"; \/\/ green\n        else if (c.confirm === 'T\u1eeb ch\u1ed1i') { confirmColor = \"#ef4444\"; cardStyle = \"background-color: #fef2f2; border: 1px solid #fca5a5;\"; }\n        else if (c.confirm === 'Xin \u0111\u1ed5i gi\u1edd') { confirmColor = \"#f97316\"; cardStyle = \"background-color: #fff7ed; border: 1px solid #fdba74;\"; }\n\n        html += `\n        <div class=\"candidate-item ${isCalling ? 'active' : ''}\" style=\"${cardStyle}\">\n          <div class=\"c-info\" style=\"flex: 1; padding-right: 16px;\">\n            <h4>\ud83d\udd52 ${formatTimeDisplay(c.time)} | ${c.name}<\/h4>\n            <p style=\"margin-bottom: 4px; font-size: 13px; color: #475569;\">Position: <strong>${c.jobTitle || \"Unspecified\"}<\/strong> | Cohort: <strong>${c.course || \"Unspecified\"}<\/strong><\/p>\n            <p>Confirmation: <span style=\"color: ${confirmColor}; font-weight: bold;\">${c.confirm}<\/span> - Check-in: ${c.checkin || 'None'}<\/p>\n            ${(c.confirm === 'T\u1eeb ch\u1ed1i' || c.confirm === 'Xin \u0111\u1ed5i gi\u1edd') && c.reason ? `<p style=\"margin-top:4px; font-size: 13px; color: #ef4444;\"><strong>Reason:<\/strong> ${c.reason}<\/p>` : ''}\n            \n            ${c.confirm === 'Xin \u0111\u1ed5i gi\u1edd' ? `\n              <div style=\"margin-top: 12px; padding: 8px; background: white; border-radius: 6px; border: 1px dashed #fdba74;\">\n                <strong style=\"font-size: 13px; color: #c2410c;\">Select new schedule:<\/strong><br\/>\n                <div style=\"display:flex; gap: 8px; margin-top: 4px;\">\n                  <input type=\"date\" id=\"date_tab2_${c.applicationId}\" class=\"emp-input\" style=\"width: auto; padding: 4px; font-size: 12px; margin-bottom: 0;\">\n                  <input type=\"time\" id=\"time_tab2_${c.applicationId}\" lang=\"en-GB\" class=\"emp-input\" style=\"width: auto; padding: 4px; font-size: 12px; margin-bottom: 0;\">\n                  <button class=\"action-btn\" style=\"background: #f97316; padding: 4px 12px;\" onclick=\"scheduleCandidate('${c.applicationId}', 'tab2_')\">Update<\/button>\n                <\/div>\n              <\/div>\n            ` : ''}\n\n            <p style=\"margin-top:4px; font-weight: bold; color: ${isCalling ? '#10b981' : '#f59e0b'};\">\n              Interview Status: ${c.status}\n            <\/p>\n            ${c.result ? `<p style=\"margin-top:4px; font-weight: bold;\">Result: <span style=\"color: ${c.result === '\u0110\u1eadu' ? '#10b981' : '#ef4444'}\">${c.result}<\/span><\/p>` : ''}\n            ${(isCalling || c.status === \"Ho\u00e0n th\u00e0nh\") ? `<textarea class=\"emp-input\" placeholder=\"Evaluation notes (Optional)...\" onchange=\"updateNote('${c.applicationId}', this.value)\" style=\"margin-top: 12px; margin-bottom: 0; padding: 8px; font-size: 13px; min-height: 60px; width: 100%; box-sizing: border-box; resize: vertical;\">${c.note || ''}<\/textarea>` : ''}\n          <\/div>\n          <div>\n            ${(() => {\n            if (c.status === \"Ho\u00e0n th\u00e0nh\") {\n              return `\n                      <div style=\"display:flex; flex-direction:column; gap:8px;\">\n                        <span style=\"color: #64748b; font-weight: bold; text-align:center;\">Evaluation:<\/span>\n                        <div style=\"display:flex; gap:8px;\">\n                           <button class=\"action-btn\" style=\"background:#10b981; padding: 8px;\" onclick=\"updateResult('${c.applicationId}', '\u0110\u1eadu')\">\u2705 Pass<\/button>\n                           <button class=\"action-btn\" style=\"background:#ef4444; padding: 8px;\" onclick=\"updateResult('${c.applicationId}', 'R\u1edbt')\">\u274c Fail<\/button>\n                        <\/div>\n                      <\/div>\n                    `;\n            }\n\n            return `\n                  <button class=\"action-btn ${isCalling ? 'btn-done' : 'btn-call'}\" onclick=\"updateStatus('${c.applicationId}', '${isCalling ? 'Ho\u00e0n th\u00e0nh' : '\u0110ang ph\u1ecfng v\u1ea5n'}')\">\n                    ${isCalling ? 'Complete (Done)' : 'Call Interview'}\n                  <\/button>\n                `;\n          })()}\n          <\/div>\n        <\/div>\n      `;\n      });\n\n      html += `<\/div><\/div>`;\n    }\n    return html;\n  }\n\n  function toggleShift(el) {\n    const body = el.nextElementSibling;\n    body.style.display = body.style.display === 'none' ? 'block' : 'none';\n    el.querySelector('span:last-child').innerText = body.style.display === 'none' ? '\u25b6' : '\u25bc';\n  }\n\n  function switchTab(tabIndex) {\n    currentActiveTab = tabIndex;\n    document.getElementById('btnTab1').classList.remove('active');\n    document.getElementById('btnTab2').classList.remove('active');\n    document.getElementById('btnTab' + tabIndex).classList.add('active');\n\n    document.getElementById('tab1').classList.remove('active');\n    document.getElementById('tab2').classList.remove('active');\n    document.getElementById('tab' + tabIndex).classList.add('active');\n  }\n\n  async function updateStatus(applicationId, newStatus) {\n    isUpdating = true;\n    const candidateIndex = employerData.findIndex(c => String(c.applicationId) === String(applicationId));\n    if (candidateIndex > -1) {\n      employerData[candidateIndex].status = newStatus;\n    }\n\n    renderEmpDashboard();\n\n    try {\n      await fetch(`${SCRIPT_URL}?action=update&candidateId=${applicationId}&employerId=${currentEmployerId}&status=${newStatus}`);\n    } catch (e) {\n      console.error(\"Update error\", e);\n    } finally {\n      lastUpdateTime = Date.now();\n      isUpdating = false;\n    }\n  }\n\n  async function updateResult(applicationId, result) {\n    isUpdating = true;\n    const candidateIndex = employerData.findIndex(c => String(c.applicationId) === String(applicationId));\n    if (candidateIndex > -1) {\n      employerData[candidateIndex].result = result;\n    }\n\n    renderEmpDashboard(true);\n\n    try {\n      await fetch(`${SCRIPT_URL}?action=update_result&candidateId=${applicationId}&employerId=${currentEmployerId}&result=${result}`);\n    } catch (e) {\n      console.error(\"Result update error\", e);\n    } finally {\n      lastUpdateTime = Date.now();\n      isUpdating = false;\n    }\n  }\n\n  async function updateNote(applicationId, note) {\n    isUpdating = true;\n    const candidateIndex = employerData.findIndex(c => String(c.applicationId) === String(applicationId));\n    if (candidateIndex > -1) {\n      employerData[candidateIndex].note = note;\n    }\n\n    try {\n      await fetch(`${SCRIPT_URL}?action=update_note&candidateId=${applicationId}&employerId=${currentEmployerId}&note=${encodeURIComponent(note)}`);\n    } catch (e) {\n      console.error(\"Note update error\", e);\n    } finally {\n      lastUpdateTime = Date.now();\n      isUpdating = false;\n    }\n  }\n\n  async function bulkSchedule() {\n    const dateInput = document.getElementById('bulkDate').value;\n    const shiftStart = document.getElementById('bulkShift').value;\n    const duration = parseInt(document.getElementById('bulkDuration').value);\n\n    if (!dateInput) {\n      await hiwAlert(\"Please select the Interview Date.\");\n      return;\n    }\n\n    const d = new Date(dateInput);\n    const formattedDate = `${String(d.getDate()).padStart(2, '0')}\/${String(d.getMonth() + 1).padStart(2, '0')}\/${String(d.getFullYear()).slice(-2)}`;\n\n    \/\/ Ch\u1ec9 h\u1eb9n gi\u1edd cho nh\u1eefng \u1ee9ng vi\u00ean CH\u01afA \u0110\u01af\u1ee2C X\u1ebeP trong DANH S\u00c1CH \u0110\u00c3 L\u1eccC\n    const unassigned = filteredData.filter(c => !c.time || !c.date);\n    if (unassigned.length === 0) {\n      await hiwAlert(\"Great! All candidates in the current view have been scheduled.\");\n      return;\n    }\n\n    \/\/ T\u00ednh to\u00e1n th\u1eddi l\u01b0\u1ee3ng ca ph\u1ecfng v\u1ea5n\n    let shiftDurationMins = 0;\n    if (shiftStart === \"08:30\") shiftDurationMins = 180; \/\/ S\u00e1ng: 8:30 - 11:30 (3 ti\u1ebfng)\n    else if (shiftStart === \"13:30\") shiftDurationMins = 180; \/\/ Chi\u1ec1u: 13:30 - 16:30 (3 ti\u1ebfng)\n    else if (shiftStart === \"18:00\") shiftDurationMins = 150; \/\/ T\u1ed1i: 18:00 - 20:30 (2.5 ti\u1ebfng)\n\n    \/\/ T\u00ednh s\u1ed1 ng\u01b0\u1eddi t\u1ed1i \u0111a ca \u0111\u00f3 c\u00f3 th\u1ec3 ch\u1ee9a\n    const maxCandidates = Math.floor(shiftDurationMins \/ duration);\n    let targetCandidates = unassigned;\n\n    if (unassigned.length > maxCandidates) {\n      const confirmMsg = `This shift has a total duration of ${shiftDurationMins} minutes. With ${duration} minutes per person, it can accommodate a maximum of ${maxCandidates} candidates.\\n\\nHowever, your list has ${unassigned.length} candidates. The system will automatically schedule ${maxCandidates} candidates into this shift, please schedule the remaining candidates into another shift later!\\n\\nDo you want to continue scheduling these ${maxCandidates} candidates?`;\n      const isOk = await hiwConfirm(confirmMsg);\n      if (!isOk) return;\n      targetCandidates = unassigned.slice(0, maxCandidates);\n    }\n\n    let previewHtml = `\n          <strong style=\"font-size:16px;\">Bulk Interview Schedule Preview:<\/strong><br><br>\n          The system has estimated the schedule for <strong>${targetCandidates.length} candidates<\/strong> (based on your position filter).<br>\n          - <strong>Date:<\/strong> ${formattedDate}<br>\n          - <strong>Start Shift:<\/strong> ${shiftStart}<br>\n          - <strong>Duration:<\/strong> ${duration} mins\/person<br>\n          <span style=\"color:#d97706; font-size: 13px;\">\ud83d\udca1 <strong>Tip:<\/strong> You can freely adjust the estimated time for each individual in the table below before clicking Confirm.<\/span><br><br>\n          \n          <div style=\"max-height: 250px; overflow-y: auto; border: 1px solid #e2e8f0; border-radius: 8px; margin-bottom: 16px;\">\n            <table style=\"width: 100%; text-align: left; border-collapse: collapse; font-size: 13px;\">\n              <thead style=\"position: sticky; top: 0; background: #f8fafc; z-index: 1;\">\n                <tr>\n                  <th style=\"padding: 10px; border-bottom: 1px solid #cbd5e1;\">Candidate<\/th>\n                  <th style=\"padding: 10px; border-bottom: 1px solid #cbd5e1;\">Position<\/th>\n                  <th style=\"padding: 10px; border-bottom: 1px solid #cbd5e1;\">Estimated Time<\/th>\n                <\/tr>\n              <\/thead>\n              <tbody>\n        `;\n\n    let tempHour = parseInt(shiftStart.split(':')[0]);\n    let tempMin = parseInt(shiftStart.split(':')[1]);\n\n    let pendingSchedules = [];\n\n    for (let i = 0; i < targetCandidates.length; i++) {\n      const c = targetCandidates[i];\n      let hh = String(tempHour).padStart(2, '0');\n      let mm = String(tempMin).padStart(2, '0');\n      let timeInput = `${hh}:${mm}`;\n\n      \/\/ B\u1ece QUA C\u00c1C KHUNG GI\u1edc \u0110\u00c3 C\u00d3 NG\u01af\u1edcI \u0110\u1eb6T TR\u01af\u1edaC \u0110\u00d3\n      while (employerData.some(other => other.date === formattedDate && other.time === timeInput)) {\n        tempMin += duration;\n        if (tempMin >= 60) {\n          tempHour += Math.floor(tempMin \/ 60);\n          tempMin = tempMin % 60;\n        }\n        hh = String(tempHour).padStart(2, '0');\n        mm = String(tempMin).padStart(2, '0');\n        timeInput = `${hh}:${mm}`;\n      }\n\n      pendingSchedules.push({ candidate: c, defaultTime: timeInput });\n\n      previewHtml += `\n                <tr>\n                  <td style=\"padding: 10px; border-bottom: 1px solid #f1f5f9;\"><strong>${c.name}<\/strong><br><span style=\"color:#64748b;\">ID: ${c.candidateId}<\/span><\/td>\n                  <td style=\"padding: 10px; border-bottom: 1px solid #f1f5f9;\">${c.jobTitle || 'Unspecified'}<\/td>\n                  <td style=\"padding: 10px; border-bottom: 1px solid #f1f5f9;\">\n                     <input type=\"time\" id=\"preview_time_${c.applicationId}\" value=\"${timeInput}\" lang=\"en-GB\" class=\"emp-input\" style=\"width:110px; padding:6px; margin:0; border: 1px solid #0f52fb;\">\n                  <\/td>\n                <\/tr>\n            `;\n\n      tempMin += duration;\n      if (tempMin >= 60) {\n        tempHour += Math.floor(tempMin \/ 60);\n        tempMin = tempMin % 60;\n      }\n    }\n\n    previewHtml += `<\/tbody><\/table><\/div>`;\n    previewHtml += `<span style=\"color: #64748b; font-size:13px;\">The invitation letter with detailed times as above will be sent automatically via Email after you click Confirm.<\/span>`;\n\n    openEmailPreview(previewHtml, async () => {\n      document.getElementById('btn-bulk').innerText = \"Processing...\";\n      document.getElementById('btn-bulk').disabled = true;\n\n      isUpdating = true;\n\n      for (let i = 0; i < pendingSchedules.length; i++) {\n        const item = pendingSchedules[i];\n        const c = item.candidate;\n\n        \/\/ Read the potentially edited time from the input field\n        const editedTimeInput = document.getElementById('preview_time_' + c.applicationId).value;\n        const timeToUse = editedTimeInput || item.defaultTime;\n\n        try {\n          const res = await fetch(`${SCRIPT_URL}?action=schedule&candidateId=${c.applicationId}&employerId=${currentEmployerId}&date=${encodeURIComponent(formattedDate)}&time=${encodeURIComponent(timeToUse)}`);\n          const result = await res.json();\n          if (result.success) {\n            c.date = formattedDate;\n            c.time = timeToUse;\n            c.confirm = \"Pending confirmation\";\n          }\n        } catch (e) {\n          console.error(\"Error scheduling candidate\", c.candidateId, e);\n        }\n      }\n\n      \/\/ Update UI first\n      renderEmpDashboard();\n\n      await hiwAlert(\"Interview scheduled successfully!\");\n\n      lastUpdateTime = Date.now();\n      isUpdating = false;\n    });\n  }\n\n  function downloadCSV(shiftName) {\n    const candidates = globalShiftsData[shiftName];\n    if (!candidates || candidates.length === 0) return;\n\n    let csv = '\\uFEFF';\n    csv += \"No.,Candidate ID,Full Name,Phone,Email,Cohort,Applied Position,Interview Time,Confirmation Status,Interview Status,Result,Notes\\n\";\n\n    candidates.forEach((c, index) => {\n      const name = (c.name || \"\").replace(\/\"\/g, '\"\"');\n      const jobTitle = (c.jobTitle || \"\").replace(\/\"\/g, '\"\"');\n      const course = (c.course || \"\").replace(\/\"\/g, '\"\"');\n      const phone = c.phone ? \"'\" + c.phone : \"\";\n      const note = (c.note || \"\").replace(\/\"\/g, '\"\"');\n\n      csv += `${index + 1},\"${c.candidateId}\",\"${name}\",\"${phone}\",\"${c.email}\",\"${course}\",\"${jobTitle}\",\"${c.time}\",\"${c.confirm}\",\"${c.status}\",\"${c.result || ''}\",\"${note}\"\\n`;\n    });\n\n    const blob = new Blob([csv], { type: 'text\/csv;charset=utf-8;' });\n    const url = URL.createObjectURL(blob);\n    const a = document.createElement('a');\n    a.href = url;\n    const dateStr = new Date().toLocaleDateString('vi-VN').replace(\/\\\/\/g, '_');\n    a.download = `HIW26_Shift_${shiftName.replace(\/[^a-zA-Z0-9_]\/g, '_')}_${dateStr}.csv`;\n    document.body.appendChild(a);\n    a.click();\n    document.body.removeChild(a);\n  }\n\n  document.addEventListener(\"DOMContentLoaded\", () => renderEmpLogin());\n<\/script>\n<!-- ============================================== -->\n<!-- CUSTOM MODAL SYSTEM                            -->\n<!-- ============================================== -->\n<style>\n  .hiw-modal-overlay {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background: rgba(15, 23, 42, 0.6);\n    backdrop-filter: blur(4px);\n    display: none;\n    align-items: center;\n    justify-content: center;\n    z-index: 99999;\n    opacity: 0;\n    transition: opacity 0.2s ease;\n  }\n\n  .hiw-modal-overlay.active {\n    display: flex;\n    opacity: 1;\n  }\n\n  .hiw-modal {\n    background: #fff;\n    width: 90%;\n    max-width: 400px;\n    border-radius: 16px;\n    padding: 24px;\n    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n    text-align: center;\n    font-family: 'Inter', sans-serif;\n    transform: scale(0.95);\n    transition: transform 0.2s ease;\n  }\n\n  .hiw-modal-overlay.active .hiw-modal {\n    transform: scale(1);\n  }\n\n  .hiw-modal-icon {\n    font-size: 40px;\n    margin-bottom: 16px;\n  }\n\n  .hiw-modal-title {\n    font-size: 20px;\n    font-weight: 700;\n    color: #0f172a;\n    margin-bottom: 8px;\n  }\n\n  .hiw-modal-text {\n    font-size: 15px;\n    color: #475569;\n    margin-bottom: 24px;\n    line-height: 1.5;\n    white-space: pre-wrap;\n  }\n\n  .hiw-modal-input {\n    width: 100%;\n    padding: 12px;\n    border: 1px solid #cbd5e1;\n    border-radius: 8px;\n    margin-bottom: 24px;\n    font-size: 15px;\n    outline: none;\n    box-sizing: border-box;\n  }\n\n  .hiw-modal-input:focus {\n    border-color: #0f52fb;\n    box-shadow: 0 0 0 3px rgba(15, 82, 251, 0.1);\n  }\n\n  .hiw-modal-actions {\n    display: flex;\n    gap: 12px;\n    justify-content: center;\n  }\n\n  .hiw-modal-btn {\n    padding: 12px 24px;\n    border: none;\n    border-radius: 8px;\n    font-size: 15px;\n    font-weight: 600;\n    cursor: pointer;\n    flex: 1;\n    transition: background 0.2s;\n  }\n\n  .hiw-modal-btn-cancel {\n    background: #f1f5f9;\n    color: #475569;\n  }\n\n  .hiw-modal-btn-cancel:hover {\n    background: #e2e8f0;\n  }\n\n  .hiw-modal-btn-primary {\n    background: #0f52fb;\n    color: #fff;\n  }\n\n  .hiw-modal-btn-primary:hover {\n    background: #003edb;\n  }\n<\/style>\n\n<div id=\"hiw-modal-overlay\" class=\"hiw-modal-overlay\">\n  <div class=\"hiw-modal\">\n    <div id=\"hiw-modal-icon\" class=\"hiw-modal-icon\">\ud83d\udd14<\/div>\n    <div id=\"hiw-modal-title\" class=\"hiw-modal-title\">Notification<\/div>\n    <div id=\"hiw-modal-text\" class=\"hiw-modal-text\"><\/div>\n    <input type=\"text\" id=\"hiw-modal-input\" class=\"hiw-modal-input\" style=\"display: none;\">\n    <div class=\"hiw-modal-actions\">\n      <button id=\"hiw-btn-cancel\" class=\"hiw-modal-btn hiw-modal-btn-cancel\" style=\"display: none;\">Cancel<\/button>\n      <button id=\"hiw-btn-ok\" class=\"hiw-modal-btn hiw-modal-btn-primary\">OK<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\n  function showCustomModal({ type = 'alert', title = 'Notification', message = '', icon = '\ud83d\udd14', inputPlaceholder = '' }) {\n    return new Promise((resolve) => {\n      const overlay = document.getElementById('hiw-modal-overlay');\n      document.getElementById('hiw-modal-icon').innerText = icon;\n      document.getElementById('hiw-modal-title').innerText = title;\n      document.getElementById('hiw-modal-text').innerText = message;\n\n      const inputObj = document.getElementById('hiw-modal-input');\n      const btnCancel = document.getElementById('hiw-btn-cancel');\n      const btnOk = document.getElementById('hiw-btn-ok');\n\n      inputObj.value = '';\n      inputObj.style.display = type === 'prompt' ? 'block' : 'none';\n      if (type === 'prompt') inputObj.placeholder = inputPlaceholder;\n\n      btnCancel.style.display = (type === 'confirm' || type === 'prompt') ? 'block' : 'none';\n\n      const cleanup = () => {\n        overlay.classList.remove('active');\n        setTimeout(() => { btnOk.onclick = null; btnCancel.onclick = null; }, 200);\n      };\n\n      btnOk.onclick = () => { cleanup(); resolve(type === 'prompt' ? inputObj.value : true); };\n      btnCancel.onclick = () => { cleanup(); resolve(type === 'prompt' ? null : false); };\n\n      overlay.classList.add('active');\n      if (type === 'prompt') setTimeout(() => inputObj.focus(), 100);\n    });\n  }\n  window.hiwAlert = (msg) => showCustomModal({ type: 'alert', message: msg, icon: '\ud83d\udd14' });\n  window.hiwConfirm = (msg) => showCustomModal({ type: 'confirm', message: msg, icon: '\u2753', title: 'Confirm' });\n  window.hiwPrompt = (msg, placeholder) => showCustomModal({ type: 'prompt', message: msg, icon: '\u270d\ufe0f', title: 'Enter Information', inputPlaceholder: placeholder });\n<\/script>\n<\/body>\n\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>\ud83d\udd14 Notification Cancel OK<\/p>\n","protected":false},"author":7359,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"slim_seo":{"title":"Schedule HIW26 Interview - Careerhub.huflit.edu.vn","description":"\ud83d\udd14 Notification Cancel OK"},"footnotes":""},"class_list":["post-91623","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Schedule HIW26 Interview - Careerhub.huflit.edu.vn<\/title>\n<meta name=\"description\" content=\"Schedule HIW26 Interview\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Schedule HIW26 Interview - Careerhub.huflit.edu.vn\" \/>\n<meta property=\"og:description\" content=\"Schedule HIW26 Interview\" \/>\n<meta property=\"og:url\" content=\"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/\" \/>\n<meta property=\"og:site_name\" content=\"Careerhub.huflit.edu.vn\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/huflitjobhub\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-04T02:19:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/careerhub.huflit.edu.vn\/wp-content\/publicmedia\/2022\/05\/JF-avtar@4x-100-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"2560\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/schedule-hiw26-interview\\\/\",\"url\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/schedule-hiw26-interview\\\/\",\"name\":\"Schedule HIW26 Interview - Careerhub.huflit.edu.vn\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/#website\"},\"datePublished\":\"2026-07-26T12:36:00+00:00\",\"dateModified\":\"2026-09-04T02:19:17+00:00\",\"description\":\"Schedule HIW26 Interview\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/schedule-hiw26-interview\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/schedule-hiw26-interview\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/schedule-hiw26-interview\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Schedule HIW26 Interview\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/\",\"name\":\"Careerhub.huflit.edu.vn\",\"description\":\"Website tuy\u1ec3n d\u1ee5ng d\u00e0nh cho sinh vi\u00ean HUFLIT\",\"publisher\":{\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/#organization\",\"name\":\"HUFLIT Job Hub\",\"url\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/wp-content\\\/uploads\\\/2022\\\/05\\\/JF-avtar@4x-100-scaled.jpg\",\"contentUrl\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/wp-content\\\/uploads\\\/2022\\\/05\\\/JF-avtar@4x-100-scaled.jpg\",\"width\":2560,\"height\":2560,\"caption\":\"HUFLIT Job Hub\"},\"image\":{\"@id\":\"https:\\\/\\\/careerhub.huflit.edu.vn\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/huflitjobhub\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Schedule HIW26 Interview - Careerhub.huflit.edu.vn","description":"Schedule HIW26 Interview","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/","og_locale":"en_US","og_type":"article","og_title":"Schedule HIW26 Interview - Careerhub.huflit.edu.vn","og_description":"Schedule HIW26 Interview","og_url":"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/","og_site_name":"Careerhub.huflit.edu.vn","article_publisher":"https:\/\/www.facebook.com\/huflitjobhub","article_modified_time":"2026-09-04T02:19:17+00:00","og_image":[{"width":2560,"height":2560,"url":"https:\/\/careerhub.huflit.edu.vn\/wp-content\/publicmedia\/2022\/05\/JF-avtar@4x-100-scaled.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/","url":"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/","name":"Schedule HIW26 Interview - Careerhub.huflit.edu.vn","isPartOf":{"@id":"https:\/\/careerhub.huflit.edu.vn\/en\/#website"},"datePublished":"2026-07-26T12:36:00+00:00","dateModified":"2026-09-04T02:19:17+00:00","description":"Schedule HIW26 Interview","breadcrumb":{"@id":"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/careerhub.huflit.edu.vn\/en\/schedule-hiw26-interview\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/careerhub.huflit.edu.vn\/en\/"},{"@type":"ListItem","position":2,"name":"Schedule HIW26 Interview"}]},{"@type":"WebSite","@id":"https:\/\/careerhub.huflit.edu.vn\/en\/#website","url":"https:\/\/careerhub.huflit.edu.vn\/en\/","name":"Careerhub.huflit.edu.vn","description":"Website tuy\u1ec3n d\u1ee5ng d\u00e0nh cho sinh vi\u00ean HUFLIT","publisher":{"@id":"https:\/\/careerhub.huflit.edu.vn\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/careerhub.huflit.edu.vn\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/careerhub.huflit.edu.vn\/en\/#organization","name":"HUFLIT Job Hub","url":"https:\/\/careerhub.huflit.edu.vn\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/careerhub.huflit.edu.vn\/en\/#\/schema\/logo\/image\/","url":"https:\/\/careerhub.huflit.edu.vn\/wp-content\/uploads\/2022\/05\/JF-avtar@4x-100-scaled.jpg","contentUrl":"https:\/\/careerhub.huflit.edu.vn\/wp-content\/uploads\/2022\/05\/JF-avtar@4x-100-scaled.jpg","width":2560,"height":2560,"caption":"HUFLIT Job Hub"},"image":{"@id":"https:\/\/careerhub.huflit.edu.vn\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/huflitjobhub"]}]}},"_links":{"self":[{"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/pages\/91623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/users\/7359"}],"replies":[{"embeddable":true,"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/comments?post=91623"}],"version-history":[{"count":1,"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/pages\/91623\/revisions"}],"predecessor-version":[{"id":91624,"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/pages\/91623\/revisions\/91624"}],"wp:attachment":[{"href":"https:\/\/careerhub.huflit.edu.vn\/en\/wp-json\/wp\/v2\/media?parent=91623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}