{"id":28,"date":"2026-08-06T18:46:30","date_gmt":"2026-08-06T18:46:30","guid":{"rendered":"https:\/\/helpnetai.com\/jobs\/?page_id=28"},"modified":"2026-08-06T21:36:38","modified_gmt":"2026-08-06T21:36:38","slug":"job-search","status":"publish","type":"page","link":"https:\/\/helpnetai.com\/jobs\/job-search\/","title":{"rendered":"Job  Search"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Enterprise Job Aggregator Portal<\/title>\n  <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/@supabase\/supabase-js@2\"><\/script>\n  <style>\n    body { font-family: -apple-system,BlinkMacSystemFont,\"Segoe UI\",Arial,sans-serif; max-width: 760px; margin: 40px auto; padding: 20px; line-height: 1.5; background:#f8f9fa; color:#0f172a; }\n    .card { border:1px solid #e2e8f0; padding:25px; border-radius:12px; margin-bottom:25px; box-shadow:0 4px 6px rgba(0,0,0,.05); background:white; }\n    input,button,select { width:100%; padding:12px; margin:10px 0; border-radius:6px; border:1px solid #cbd5e1; box-sizing:border-box; }\n    button { background:#0284c7; color:white; border:0; font-weight:700; cursor:pointer; }\n    button:hover { background:#0369a1; }\n    button:disabled { opacity:.55; cursor:not-allowed; }\n    .hidden { display:none; }\n    .job-item { border-bottom:1px solid #f1f5f9; padding:15px 0; }\n    .admin-badge { background:#dc2626; color:white; padding:3px 8px; border-radius:4px; font-size:.75em; font-weight:700; }\n    .user-row { display:flex; gap:12px; justify-content:space-between; align-items:center; border-bottom:1px solid #f1f5f9; padding:10px 0; }\n    .user-row > div:first-child { min-width:0; overflow-wrap:anywhere; }\n    .status-toggle { width:auto; margin:0; padding:6px; }\n    .warning { color:#92400e; background:#fef3c7; padding:10px; border-radius:6px; margin-bottom:15px; }\n    .error { color:#991b1b; }\n    a { color:#0284c7; }\n  \n.results-summary{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;color:#475569;font-size:.92rem}\n.job-item{border:1px solid #e2e8f0;border-radius:10px;padding:18px;margin:12px 0;background:#fff}\n.job-meta{color:#64748b;font-size:.9rem;margin:7px 0}.job-description{margin:10px 0;white-space:pre-line}\n.details-btn,.pagination button{width:auto}.details-btn{background:transparent;color:#0284c7;padding:4px 0}\n.pagination{display:flex;justify-content:center;align-items:center;gap:6px;margin-top:22px;flex-wrap:wrap}\n.pagination button{margin:0;padding:8px 11px;background:#e2e8f0;color:#0f172a}.pagination button.active{background:#0284c7;color:white}\n\n    \/* V3.1 WordPress full-width layout *\/\n    body {\n      max-width: none;\n      width: 100%;\n      margin: 0 auto;\n      padding: 24px clamp(16px, 3vw, 48px);\n      box-sizing: border-box;\n    }\n    .card {\n      width: 100%;\n      box-sizing: border-box;\n    }\n    #authSection button,\n    #searchSection button,\n    #adminSection > button {\n      width: auto;\n      min-width: 150px;\n      padding: 10px 24px;\n      display: block;\n      margin: 10px auto;\n    }\n    #searchBtn {\n      min-width: 190px;\n    }\n    #logoutBtn {\n      min-width: 130px;\n    }\n    .status-toggle {\n      width: auto;\n      margin: 0;\n    }\n    .details-btn {\n      display: inline-block;\n      min-width: 0;\n      margin: 4px 0;\n      padding: 4px 0;\n    }\n    .pagination button {\n      display: inline-block;\n      width: auto;\n      min-width: 42px;\n      margin: 0;\n      padding: 8px 11px;\n    }\n\n\n    \/* V3.3: results content alignment *\/\n    #resultsCard,\n    #resultsFeed,\n    #resultsFeed .results-summary,\n    #resultsFeed .job-item,\n    #resultsFeed .job-item div,\n    #resultsFeed .job-item span,\n    #resultsFeed .job-item p {\n      text-align: left;\n    }\n    #resultsFeed .job-item {\n      margin-left: 0;\n      margin-right: 0;\n    }\n    #resultsFeed .pagination {\n      text-align: center;\n    }\n\n<\/style>\n<\/head>\n<body>\n  <h2>\ud83d\udcbc Enterprise Job Portal<\/h2>\n\n  <div id=\"authSection\" class=\"card\">\n    <h3>User Authentication<\/h3>\n    <input type=\"email\" id=\"email\" placeholder=\"Your Email Address\" autocomplete=\"email\" required>\n    <input type=\"password\" id=\"password\" placeholder=\"Password\" autocomplete=\"current-password\" required>\n    <button id=\"loginBtn\">Sign In<\/button>\n    <button id=\"signUpBtn\" style=\"background:#10b981\">Create Account<\/button>\n  <\/div>\n\n  <div id=\"adminSection\" class=\"card hidden\" style=\"border-left:5px solid #dc2626\">\n    <h3>\ud83d\udee1\ufe0f Admin Dashboard: User Management<\/h3>\n    <p style=\"text-align:center\"><a href=\"\/jobs\/Job-Analytics-v1.html\" target=\"_blank\" rel=\"noopener\"><strong>Open Job Market Analytics \u2192<\/strong><\/a><\/p>\n    <div id=\"userManagementList\">Loading users&#8230;<\/div>\n  <\/div>\n\n  <div id=\"searchSection\" class=\"card hidden\">\n    <h3>Search Real-Time Openings<\/h3>\n    <p>Active Profile: <strong id=\"userDisplay\"><\/strong> <span id=\"roleBadge\"><\/span><\/p>\n    <div id=\"approvalWarning\" class=\"warning hidden\">\u26a0\ufe0f Your account is pending administrator approval. Real-time search is locked.<\/div>\n    <div id=\"searchFormBlock\">\n      <input type=\"text\" id=\"jobTitle\" placeholder=\"e.g. Lead DevOps Engineer\" required>\n      <input type=\"text\" id=\"location\" placeholder=\"e.g. Bengaluru, India\" required>\n      <button id=\"searchBtn\">Execute Deep Search<\/button>\n    <\/div>\n    <button id=\"logoutBtn\" style=\"background:#64748b;margin-top:20px\">Sign Out<\/button>\n  <\/div>\n\n  <div id=\"resultsCard\" class=\"card hidden\">\n    <h3>Aggregated Results<\/h3>\n    <div id=\"resultsFeed\"><\/div>\n  <\/div>\n\n<script>\nconst SUPABASE_URL = \"https:\/\/vubuujwrsowpnfcengfq.supabase.co\";\nconst SUPABASE_ANON_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ1YnV1andyc293cG5mY2VuZ2ZxIiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODYwMDU0NDQsImV4cCI6MjEwMTU4MTQ0NH0.TSg9vXaNkPFWeL6A162O1vENoFmCRnlesdhXMoEVSW4\";\nconst N8N_WEBHOOK_URL = \"https:\/\/auto.helpnetai.com\/webhook\/2636eca1-ab03-4ebf-8761-5655043ee80e\";\nlet supabaseClient;\n\nconst $ = (id) => document.getElementById(id);\nconst escapeHtml = (value) => String(value ?? '').replace(\/[&<>\"']\/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#039;'}[c]));\nconst safeUrl = (value) => {\n  try {\n    const u = new URL(value);\n    return ['http:', 'https:'].includes(u.protocol) ? u.href : '#';\n  } catch { return '#'; }\n};\n\nlet allJobs=[]; let currentPage=1; const PAGE_SIZE=10;\nwindow.addEventListener('DOMContentLoaded', async () => {\n  if (!window.supabase?.createClient) {\n    alert('Supabase JS failed to load. Check the CDN\/network.');\n    return;\n  }\n  supabaseClient = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);\n\n  $('loginBtn').addEventListener('click', handleLogin);\n  $('signUpBtn').addEventListener('click', handleSignUp);\n  $('searchBtn').addEventListener('click', handleSearch);\n  $('logoutBtn').addEventListener('click', handleLogout);\n\n  supabaseClient.auth.onAuthStateChange(() => setTimeout(checkSession, 0));\n  await checkSession();\n});\n\nasync function handleLogin() {\n  const email = $('email').value.trim();\n  const password = $('password').value;\n  if (!email || !password) return alert('Please enter email and password.');\n  const { error } = await supabaseClient.auth.signInWithPassword({ email, password });\n  if (error) alert('Sign-in failed: ' + error.message);\n}\n\nasync function handleSignUp() {\n  const email = $('email').value.trim();\n  const password = $('password').value;\n  if (!email || !password) return alert('Please enter email and password.');\n  if (password.length < 6) return alert('Password must be at least 6 characters.');\n  const { data, error } = await supabaseClient.auth.signUp({ email, password });\n  if (error) return alert('Sign-up failed: ' + error.message);\n  alert(data.session ? 'Account created and signed in.' : 'Account created. Check your email if confirmation is enabled.');\n  await checkSession();\n}\n\nasync function checkSession() {\n  const { data: { session } } = await supabaseClient.auth.getSession();\n  if (!session) {\n    $('authSection').classList.remove('hidden');\n    $('searchSection').classList.add('hidden');\n    $('adminSection').classList.add('hidden');\n    $('resultsCard').classList.add('hidden');\n    return;\n  }\n\n  $('authSection').classList.add('hidden');\n  $('searchSection').classList.remove('hidden');\n  $('userDisplay').textContent = session.user.email || session.user.id;\n\n  const { data: profile, error } = await supabaseClient\n    .from('profiles')\n    .select('role,is_approved')\n    .eq('id', session.user.id)\n    .single();\n\n  if (error || !profile) {\n    $('approvalWarning').textContent = 'Unable to load your profile: ' + (error?.message || 'Profile missing');\n    $('approvalWarning').classList.remove('hidden');\n    $('searchFormBlock').classList.add('hidden');\n    $('adminSection').classList.add('hidden');\n    return;\n  }\n\n  const allowed = profile.role === 'admin' || profile.is_approved === true;\n  $('approvalWarning').classList.toggle('hidden', allowed);\n  $('searchFormBlock').classList.toggle('hidden', !allowed);\n\n  if (profile.role === 'admin') {\n    $('roleBadge').innerHTML = '<span class=\"admin-badge\">ADMIN<\/span>';\n    $('adminSection').classList.remove('hidden');\n    await loadAdminUserDirectory();\n  } else {\n    $('roleBadge').textContent = '';\n    $('adminSection').classList.add('hidden');\n  }\n}\n\nasync function loadAdminUserDirectory() {\n  const { data: users, error } = await supabaseClient\n    .from('profiles')\n    .select('id,email,role,is_approved,updated_at')\n    .order('updated_at', { ascending:false });\n\n  if (error) {\n    $('userManagementList').textContent = 'Error loading users: ' + error.message;\n    return;\n  }\n\n  $('userManagementList').innerHTML = users.map(user => `\n    <div class=\"user-row\">\n      <div><strong>${escapeHtml(user.email)}<\/strong><br><small>${escapeHtml(user.role)}<\/small><\/div>\n      <div>\n        <select class=\"status-toggle\" data-user-id=\"${escapeHtml(user.id)}\">\n          <option value=\"false\" ${!user.is_approved ? 'selected' : ''}>Pending \/ Blocked<\/option>\n          <option value=\"true\" ${user.is_approved ? 'selected' : ''}>Approved Active<\/option>\n        <\/select>\n      <\/div>\n    <\/div>`).join('');\n\n  document.querySelectorAll('.status-toggle').forEach(el => {\n    el.addEventListener('change', () => toggleUserApproval(el.dataset.userId, el.value === 'true'));\n  });\n}\n\nasync function toggleUserApproval(userId, isApproved) {\n  const { error } = await supabaseClient.rpc('update_user_approval', {\n    target_user_id: userId,\n    approval_status: isApproved\n  });\n  if (error) return alert('Approval update failed: ' + error.message);\n  await loadAdminUserDirectory();\n}\n\nasync function handleSearch() {\n  const job_title = $('jobTitle').value.trim();\n  const location = $('location').value.trim();\n  if (!job_title || !location) return alert('Please enter both job title and location.');\n\n  const { data: { session } } = await supabaseClient.auth.getSession();\n  if (!session) return alert('Your session has expired. Please sign in again.');\n\n  $('searchBtn').disabled = true;\n  $('resultsFeed').textContent = 'Searching current openings...';\n  $('resultsCard').classList.remove('hidden');\n\n  try {\n    const response = await fetch(N8N_WEBHOOK_URL, {\n      method:'POST',\n      headers:{ 'Content-Type':'application\/json' },\n      body:JSON.stringify({ job_title, location, user_jwt: session.access_token })\n    });\n\n    let payload;\n    const contentType = response.headers.get('content-type') || '';\n    payload = contentType.includes('application\/json') ? await response.json() : { error: await response.text() };\n\n    if (!response.ok) throw new Error(payload?.error || payload?.message || `Request failed (${response.status})`);\n    const jobs = Array.isArray(payload)\n      ? payload.flatMap(item => {\n          if (item && Array.isArray(item.jobs)) return item.jobs;\n          if (item && item.json && Array.isArray(item.json.jobs)) return item.json.jobs;\n          if (item && item.json && item.json.title) return [item.json];\n          return item && item.title ? [item] : [];\n        })\n      : (Array.isArray(payload?.jobs) ? payload.jobs\n        : payload?.title ? [payload]\n        : payload?.json?.title ? [payload.json]\n        : []);\n    renderJobs(jobs);\n  } catch (err) {\n    const message = err instanceof TypeError\n      ? 'Search service unavailable. This service accepts browser requests only from https:\/\/jobs.helpnetai.com.'\n      : (err.message || 'Search failed.');\n    $('resultsFeed').innerHTML = `<span class=\"error\">${escapeHtml(message)}<\/span>`;\n  } finally {\n    $('searchBtn').disabled = false;\n  }\n}\n\nfunction renderJobs(jobs,page=1){\n  allJobs=Array.isArray(jobs)?jobs:[];\n  if(!allJobs.length){$('resultsFeed').textContent='No active openings matched the criteria.';return;}\n  const pages=Math.ceil(allJobs.length\/PAGE_SIZE);\n  currentPage=Math.min(Math.max(1,page),pages);\n  const s=(currentPage-1)*PAGE_SIZE, shown=allJobs.slice(s,s+PAGE_SIZE);\n  const cards=shown.map((job,i)=>{\n    const x=job.raw_extensions||{}, desc=String(job.description||'').trim();\n    const short=desc.length>320?desc.slice(0,320).trimEnd()+'\u2026':desc, id=`desc-${s+i}`;\n    const meta=[job.location&&`\ud83d\udccd ${escapeHtml(job.location)}`,(x.schedule_type||job.schedule_type)&&`\ud83d\udd52 ${escapeHtml(x.schedule_type||job.schedule_type)}`,(x.posted_at||job.posted_at)&&`\ud83d\udcc5 ${escapeHtml(x.posted_at||job.posted_at)}`,job.via&&`Source: ${escapeHtml(job.via)}`].filter(Boolean).join(' \u00b7 ');\n    const salary=job.salary_min!=null?`<div>\ud83d\udcb0 ${escapeHtml(job.salary_currency||'')} ${escapeHtml(job.salary_min)}${job.salary_max!=null?' - '+escapeHtml(job.salary_max):''}<\/div>`:'';\n    const link=safeUrl(job.apply_link);\n    return `<article class=\"job-item\"><strong>${escapeHtml(job.title||'Untitled')}<\/strong><br><span>${escapeHtml(job.company_name||'Unknown company')}<\/span><div class=\"job-meta\">${meta}<\/div>${salary}${desc?`<div id=\"${id}\" class=\"job-description\" data-short=\"${escapeHtml(short)}\" data-full=\"${escapeHtml(desc)}\">${escapeHtml(short)}<\/div>${desc.length>320?`<button class=\"details-btn\" data-target=\"${id}\">Show details<\/button>`:''}`:''}${link!=='#'?`<br><a href=\"${escapeHtml(link)}\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>View Original Posting \u2192<\/strong><\/a>`:''}<\/article>`;\n  }).join('');\n  let nav='';\n  if(pages>1){\n    let buttons=`<button data-page=\"${currentPage-1}\" ${currentPage===1?'disabled':''}>\u2190 Previous<\/button>`;\n    for(let n=1;n<=pages;n++) buttons+=`<button data-page=\"${n}\" class=\"${n===currentPage?'active':''}\">${n}<\/button>`;\n    buttons+=`<button data-page=\"${currentPage+1}\" ${currentPage===pages?'disabled':''}>Next \u2192<\/button>`;\n    nav=`<nav class=\"pagination\">${buttons}<\/nav>`;\n  }\n  $('resultsFeed').innerHTML=`<div class=\"results-summary\"><span><strong>${allJobs.length}<\/strong> jobs found<\/span><span>Showing ${s+1}\u2013${s+shown.length}<\/span><\/div>${cards}${nav}`;\n  document.querySelectorAll('.details-btn').forEach(btn=>btn.onclick=()=>{const el=$(btn.dataset.target),open=btn.textContent==='Hide details';el.textContent=open?el.dataset.short:el.dataset.full;btn.textContent=open?'Show details':'Hide details';});\n  document.querySelectorAll('[data-page]').forEach(btn=>btn.onclick=()=>{const n=Number(btn.dataset.page);if(n>=1&&n<=pages){renderJobs(allJobs,n);$('resultsCard').scrollIntoView({behavior:'smooth'});}});\n}\n\nasync function handleLogout() {\n  await supabaseClient.auth.signOut();\n}\n<\/script>\n<\/body>\n<\/html>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Enterprise Job Aggregator Portal \ud83d\udcbc Enterprise Job Portal User Authentication Sign In Create Account \ud83d\udee1\ufe0f Admin Dashboard: User Management Open Job Market Analytics \u2192 Loading users&#8230; Search Real-Time Openings Active Profile: \u26a0\ufe0f Your account is pending administrator approval. Real-time search is locked. Execute Deep Search Sign Out Aggregated Results<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"class_list":["post-28","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/pages\/28","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/comments?post=28"}],"version-history":[{"count":13,"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/pages\/28\/revisions"}],"predecessor-version":[{"id":48,"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/pages\/28\/revisions\/48"}],"wp:attachment":[{"href":"https:\/\/helpnetai.com\/jobs\/wp-json\/wp\/v2\/media?parent=28"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}