Spaces:
Configuration error
Configuration error
| {% extends "base.html" %} | |
| {% block title %}Profile - AI Resume Builder{% endblock %} | |
| {% block content %} | |
| <div class="min-h-screen bg-gray-50"> | |
| <!-- Header --> | |
| <header class="bg-white shadow-sm border-b border-gray-200"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex justify-between items-center py-4"> | |
| <div class="flex items-center"> | |
| <h1 class="text-2xl font-bold text-gray-900">My Profile</h1> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| {% if current_user.is_admin %} | |
| <div class="relative"> | |
| <button onclick="toggleDropdown()" class="text-sm text-gray-600 hover:text-gray-800 flex items-center space-x-1"> | |
| <span>Welcome, {{ current_user.name }}</span> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> | |
| </svg> | |
| </button> | |
| <div id="adminDropdown" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 z-50 border border-gray-200"> | |
| <a href="{{ url_for('admin_panel') }}" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"> | |
| <i class="fas fa-shield-alt mr-2"></i>Admin Panel | |
| </a> | |
| <div class="border-t border-gray-100"></div> | |
| <a href="{{ url_for('logout') }}" class="block px-4 py-2 text-sm text-red-600 hover:bg-gray-100"> | |
| Logout | |
| </a> | |
| </div> | |
| </div> | |
| {% else %} | |
| <span class="text-sm text-gray-600">Welcome, {{ current_user.name }}</span> | |
| <a href="{{ url_for('logout') }}" class="text-sm text-red-600 hover:text-red-500"> | |
| Logout | |
| </a> | |
| {% endif %} | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8"> | |
| <div class="px-4 py-6 sm:px-0"> | |
| {% if has_profile %} | |
| <!-- Profile Display --> | |
| <div class="bg-white rounded-lg shadow p-6 mb-6"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-xl font-semibold text-gray-800">Your Professional Profile</h2> | |
| <div class="flex space-x-3"> | |
| <button onclick="showResumeOptions()" class="bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"> | |
| <i class="fas fa-download mr-2"></i>Generate Resume | |
| </button> | |
| <a href="{{ url_for('create_introduction') }}" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"> | |
| <i class="fas fa-edit mr-2"></i>Edit Profile | |
| </a> | |
| </div> | |
| </div> | |
| <!-- Display sections based on user's order --> | |
| {% for section_name in section_order %} | |
| {% if section_name == 'introduction' and intro %} | |
| <div class="mb-8"> | |
| <div class="text-center mb-6"> | |
| <h3 class="text-2xl font-bold text-gray-900 mb-2">{{ intro.name }}</h3> | |
| <div class="flex justify-center flex-wrap gap-4 text-sm text-gray-600"> | |
| <span><i class="fas fa-envelope mr-1"></i> {{ intro.email }}</span> | |
| <span><i class="fas fa-phone mr-1"></i> {{ intro.phone }}</span> | |
| {% if intro.linkedin %} | |
| <span><i class="fab fa-linkedin mr-1"></i> LinkedIn</span> | |
| {% endif %} | |
| {% if intro.github %} | |
| <span><i class="fab fa-github mr-1"></i> GitHub</span> | |
| {% endif %} | |
| {% if intro.website %} | |
| <span><i class="fas fa-globe mr-1"></i> Website</span> | |
| {% endif %} | |
| </div> | |
| </div> | |
| </div> | |
| {% endif %} | |
| {% if section_name == 'profile_summary' and summary %} | |
| <div class="mb-8"> | |
| <h4 class="text-lg font-semibold text-gray-800 mb-3">Professional Summary</h4> | |
| <p class="text-gray-700 leading-relaxed">{{ summary.summary }}</p> | |
| {% if summary.ai_generated %} | |
| <span class="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded mt-2">AI Generated</span> | |
| {% endif %} | |
| </div> | |
| {% endif %} | |
| {% if section_name == 'work_experience' and work_experiences %} | |
| <div class="mb-8"> | |
| <h4 class="text-lg font-semibold text-gray-800 mb-4">Work Experience</h4> | |
| {% for exp in work_experiences %} | |
| <div class="mb-4 pb-4 border-b border-gray-200 last:border-0"> | |
| <h5 class="font-medium text-gray-900">{{ exp.title }}</h5> | |
| <p class="text-gray-600 text-sm">{{ exp.organization }}</p> | |
| <p class="text-gray-500 text-sm mb-2"> | |
| {{ exp.start_month }}/{{ exp.start_year }} - | |
| {% if exp.end_year %}{{ exp.end_month }}/{{ exp.end_year }}{% else %}Present{% endif %} | |
| </p> | |
| {% if exp.remarks %} | |
| <p class="text-gray-700 text-sm">{{ exp.remarks }}</p> | |
| {% endif %} | |
| </div> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| {% if section_name == 'projects' and projects %} | |
| <div class="mb-8"> | |
| <h4 class="text-lg font-semibold text-gray-800 mb-4">Projects</h4> | |
| {% for project in projects %} | |
| <div class="mb-4 pb-4 border-b border-gray-200 last:border-0"> | |
| <h5 class="font-medium text-gray-900">{{ project.title }}</h5> | |
| {% if project.organization %} | |
| <p class="text-gray-600 text-sm">{{ project.organization }}</p> | |
| {% endif %} | |
| <p class="text-gray-500 text-sm mb-2"> | |
| {{ project.start_month }}/{{ project.start_year }} - | |
| {% if project.end_year %}{{ project.end_month }}/{{ project.end_year }}{% else %}Present{% endif %} | |
| </p> | |
| {% if project.remarks %} | |
| <p class="text-gray-700 text-sm">{{ project.remarks }}</p> | |
| {% endif %} | |
| </div> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| {% if section_name == 'education' and educations %} | |
| <div class="mb-8"> | |
| <h4 class="text-lg font-semibold text-gray-800 mb-4">Education</h4> | |
| {% for edu in educations %} | |
| <div class="mb-4 pb-4 border-b border-gray-200 last:border-0"> | |
| <h5 class="font-medium text-gray-900">{{ edu.title }}</h5> | |
| <p class="text-gray-600 text-sm">{{ edu.organization }}</p> | |
| <p class="text-gray-500 text-sm mb-2"> | |
| {{ edu.start_month }}/{{ edu.start_year }} - | |
| {% if edu.end_year %}{{ edu.end_month }}/{{ edu.end_year }}{% else %}Present{% endif %} | |
| </p> | |
| {% if edu.remarks %} | |
| <p class="text-gray-700 text-sm">{{ edu.remarks }}</p> | |
| {% endif %} | |
| </div> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| {% if section_name == 'skills' and skills %} | |
| <div class="mb-8"> | |
| <h4 class="text-lg font-semibold text-gray-800 mb-3">Skills</h4> | |
| <div class="flex flex-wrap gap-2"> | |
| {% for skill in skills %} | |
| <span class="bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm">{{ skill.skill }}</span> | |
| {% endfor %} | |
| </div> | |
| </div> | |
| {% endif %} | |
| {% if section_name == 'achievements' and achievements %} | |
| <div class="mb-8"> | |
| <h4 class="text-lg font-semibold text-gray-800 mb-3">Achievements</h4> | |
| <div class="flex flex-wrap gap-2"> | |
| {% for achievement in achievements %} | |
| <span class="bg-green-100 text-green-800 px-3 py-1 rounded-full text-sm">{{ achievement.achievement }}</span> | |
| {% endfor %} | |
| </div> | |
| </div> | |
| {% endif %} | |
| {% endfor %} | |
| </div> | |
| {% else %} | |
| <!-- Empty State --> | |
| <div class="bg-white rounded-lg shadow p-6"> | |
| <div class="text-center"> | |
| <h2 class="text-xl font-semibold text-gray-800 mb-4">Welcome to AI Resume Builder!</h2> | |
| <p class="text-gray-600 mb-6"> | |
| Your profile is currently empty. Click the button below to start creating your professional resume. | |
| </p> | |
| <a href="{{ url_for('create_introduction') }}" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition-colors inline-block"> | |
| Create Your Profile | |
| </a> | |
| </div> | |
| </div> | |
| {% endif %} | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Resume Options Modal --> | |
| <div id="resumeModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50"> | |
| <div class="bg-white rounded-lg p-6 m-4 max-w-md w-full"> | |
| <h3 class="text-lg font-semibold text-gray-900 mb-4">Choose Resume Format</h3> | |
| <div class="space-y-3"> | |
| <button onclick="generateResume('pdf-standard')" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"> | |
| <i class="fas fa-file-pdf mr-2"></i>Generate PDF (Standard) | |
| </button> | |
| <button onclick="generateResume('pdf-modern')" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"> | |
| <i class="fas fa-file-pdf mr-2"></i>Generate PDF (Modern) | |
| </button> | |
| <button onclick="generateResume('word')" class="w-full bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"> | |
| <i class="fas fa-file-word mr-2"></i>Generate Word Document | |
| </button> | |
| </div> | |
| <button onclick="hideResumeOptions()" class="mt-4 w-full bg-gray-300 hover:bg-gray-400 text-gray-800 font-medium py-2 px-4 rounded-lg transition-colors"> | |
| Cancel | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| function showResumeOptions() { | |
| document.getElementById('resumeModal').classList.remove('hidden'); | |
| document.getElementById('resumeModal').classList.add('flex'); | |
| } | |
| function hideResumeOptions() { | |
| document.getElementById('resumeModal').classList.add('hidden'); | |
| document.getElementById('resumeModal').classList.remove('flex'); | |
| } | |
| function generateResume(format) { | |
| // Show loading state | |
| const modal = document.getElementById('resumeModal'); | |
| const buttons = modal.querySelectorAll('button'); | |
| buttons.forEach(btn => btn.disabled = true); | |
| // Create and show loading message | |
| const loadingMsg = document.createElement('div'); | |
| loadingMsg.className = 'text-center mt-4 text-gray-600'; | |
| loadingMsg.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Generating your resume...'; | |
| modal.querySelector('.bg-white').appendChild(loadingMsg); | |
| // Fetch the resume | |
| fetch(`/profile/generate-resume/${format}`, { | |
| method: 'GET', | |
| headers: { | |
| 'X-Requested-With': 'XMLHttpRequest' | |
| } | |
| }) | |
| .then(response => { | |
| if (!response.ok) { | |
| throw new Error('Failed to generate resume'); | |
| } | |
| return response.blob(); | |
| }) | |
| .then(blob => { | |
| // Create download link | |
| const url = window.URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| // Set filename based on format | |
| const username = '{{ current_user.name }}'.replace(/\s+/g, '_'); | |
| if (format === 'pdf-standard') { | |
| a.download = `${username}_resume.pdf`; | |
| } else if (format === 'pdf-modern') { | |
| a.download = `${username}_resume_modern.pdf`; | |
| } else if (format === 'word') { | |
| a.download = `${username}_resume.docx`; | |
| } | |
| document.body.appendChild(a); | |
| a.click(); | |
| window.URL.revokeObjectURL(url); | |
| document.body.removeChild(a); | |
| hideResumeOptions(); | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| alert('Failed to generate resume. Please try again.'); | |
| hideResumeOptions(); | |
| }) | |
| .finally(() => { | |
| // Remove loading message and re-enable buttons | |
| if (loadingMsg.parentNode) { | |
| loadingMsg.parentNode.removeChild(loadingMsg); | |
| } | |
| buttons.forEach(btn => btn.disabled = false); | |
| }); | |
| } | |
| // Toggle admin dropdown | |
| function toggleDropdown() { | |
| const dropdown = document.getElementById('adminDropdown'); | |
| dropdown.classList.toggle('hidden'); | |
| // Close dropdown when clicking outside | |
| document.addEventListener('click', function closeDropdown(e) { | |
| if (!e.target.closest('.relative')) { | |
| dropdown.classList.add('hidden'); | |
| document.removeEventListener('click', closeDropdown); | |
| } | |
| }); | |
| } | |
| </script> | |
| {% endblock %} |