Spaces:
Runtime error
Runtime error
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AI Resume Analyzer</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <script src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script> | |
| <style> | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50"> | |
| <div class="min-h-screen"> | |
| <!-- Navbar --> | |
| <nav class="bg-white shadow-sm"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex justify-between h-16 items-center"> | |
| <div class="flex items-center"> | |
| <svg class="h-8 w-8 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /> | |
| </svg> | |
| <span class="ml-2 text-xl font-semibold text-gray-900">AI Resume Analyzer</span> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Main Content --> | |
| <main class="max-w-7xl mx-auto py-12 sm:px-6 lg:px-8"> | |
| <div class="max-w-3xl mx-auto"> | |
| <!-- Hero Section --> | |
| <div class="text-center mb-12"> | |
| <h1 class="text-4xl font-bold text-gray-900 mb-4"> | |
| Predict Your Ideal Job Title | |
| </h1> | |
| <p class="text-lg text-gray-600"> | |
| Upload your resume and let AI analyze your skills and experience | |
| </p> | |
| </div> | |
| <!-- Upload Card --> | |
| <div class="bg-white rounded-2xl shadow-xl p-8 mb-8"> | |
| <form id="uploadForm" class="space-y-6"> | |
| <div class="flex flex-col items-center justify-center border-2 border-dashed border-gray-300 rounded-lg p-6 hover:border-indigo-500 transition-colors"> | |
| <div class="space-y-2 text-center"> | |
| <svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48"> | |
| <path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> | |
| </svg> | |
| <div class="text-sm text-gray-600"> | |
| <label for="resume" class="relative cursor-pointer rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500"> | |
| <span>Upload a file</span> | |
| <input id="resume" name="resume" type="file" class="sr-only" accept=".pdf"> | |
| </label> | |
| <p class="pl-1">or drag and drop</p> | |
| </div> | |
| <p class="text-xs text-gray-500">PDF up to 10MB</p> | |
| </div> | |
| </div> | |
| <div class="text-center"> | |
| <button type="submit" class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-full shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> | |
| Analyze Resume | |
| </button> | |
| </div> | |
| </form> | |
| <!-- Loading State --> | |
| <div id="loading" class="hidden text-center py-8"> | |
| <lottie-player src="https://assets2.lottiefiles.com/packages/lf20_poqmycwy.json" background="transparent" speed="1" style="width: 200px; height: 200px; margin: 0 auto;" loop autoplay></lottie-player> | |
| <p class="mt-4 text-gray-600">Analyzing your resume...</p> | |
| </div> | |
| <!-- Results Section --> | |
| <div id="result" class="hidden mt-8"> | |
| <div class="space-y-6"> | |
| <!-- Predicted Title --> | |
| <div class="bg-gradient-to-r from-indigo-50 to-blue-50 rounded-xl p-6"> | |
| <h3 class="text-lg font-medium text-gray-900 mb-2">Predicted Job Title</h3> | |
| <p id="predictedTitle" class="text-2xl font-bold text-indigo-600"></p> | |
| </div> | |
| <!-- Skills --> | |
| <div class="bg-white rounded-xl border border-gray-200 p-6"> | |
| <h3 class="text-lg font-medium text-gray-900 mb-4">Extracted Skills</h3> | |
| <div id="extractedSkills" class="flex flex-wrap gap-2"> | |
| <!-- Skills will be inserted here as tags --> | |
| </div> | |
| </div> | |
| <!-- Organization --> | |
| <div class="bg-white rounded-xl border border-gray-200 p-6"> | |
| <h3 class="text-lg font-medium text-gray-900 mb-2">Functional Area</h3> | |
| <p id="organization" class="text-gray-700"></p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |
| <script> | |
| $(document).ready(function() { | |
| // File input visual feedback | |
| $('#resume').on('change', function(e) { | |
| const fileName = e.target.files[0]?.name; | |
| if (fileName) { | |
| $(this).closest('.border-dashed').find('p').text(fileName); | |
| } | |
| }); | |
| // Drag and drop functionality | |
| const dropZone = $('.border-dashed'); | |
| dropZone.on('dragover', function(e) { | |
| e.preventDefault(); | |
| $(this).addClass('border-indigo-500'); | |
| }); | |
| dropZone.on('dragleave', function(e) { | |
| e.preventDefault(); | |
| $(this).removeClass('border-indigo-500'); | |
| }); | |
| dropZone.on('drop', function(e) { | |
| e.preventDefault(); | |
| $(this).removeClass('border-indigo-500'); | |
| const files = e.originalEvent.dataTransfer.files; | |
| $('#resume')[0].files = files; | |
| if (files[0]) { | |
| $(this).find('p').text(files[0].name); | |
| } | |
| }); | |
| // Form submission | |
| $('#uploadForm').on('submit', function(e) { | |
| e.preventDefault(); | |
| const formData = new FormData(); | |
| const fileInput = $('#resume')[0]; | |
| if (fileInput.files.length === 0) { | |
| alert('Please select a file'); | |
| return; | |
| } | |
| formData.append('resume', fileInput.files[0]); | |
| $('#loading').removeClass('hidden'); | |
| $('#result').addClass('hidden'); | |
| $.ajax({ | |
| url: '/predict', | |
| type: 'POST', | |
| data: formData, | |
| processData: false, | |
| contentType: false, | |
| success: function(response) { | |
| $('#loading').addClass('hidden'); | |
| $('#result').removeClass('hidden'); | |
| // Update results | |
| $('#predictedTitle').text(response.predicted_title); | |
| // Convert skills string to tags | |
| const skills = response.extracted_skills.split(', '); | |
| const skillsHtml = skills.map(skill => | |
| `<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-indigo-100 text-indigo-800"> | |
| ${skill} | |
| </span>` | |
| ).join(''); | |
| $('#extractedSkills').html(skillsHtml); | |
| $('#organization').html(response.area.replaceAll(", ","<br/>")); | |
| }, | |
| error: function(xhr) { | |
| $('#loading').addClass('hidden'); | |
| alert('Error: ' + (xhr.responseJSON?.error || 'Something went wrong')); | |
| } | |
| }); | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> |