Spaces:
Sleeping
Sleeping
<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> |