update changes

This commit is contained in:
raman 2025-08-18 10:39:18 +05:30
parent 672551cd0a
commit b479fee7c9
9 changed files with 165 additions and 29 deletions

View File

@ -23,7 +23,7 @@ class ATSController(http.Controller):
@http.route('/myATS/page/<string:page>', type='http', auth='user', website=True) @http.route('/myATS/page/<string:page>', type='http', auth='user', website=True)
def render_partial_content(self, page, **kwargs): def render_partial_content(self, page, **kwargs):
if page == "job_requests": if page in ["job_requests","jobs"]:
jobs = request.env['hr.job.recruitment'].search([], order='create_date desc') jobs = request.env['hr.job.recruitment'].search([], order='create_date desc')
return request.render('hr_recruitment_web_app.job_list_partial_page', {'jobs': jobs}) return request.render('hr_recruitment_web_app.job_list_partial_page', {'jobs': jobs})
elif page == "applicants": elif page == "applicants":
@ -56,6 +56,17 @@ class ATSController(http.Controller):
} }
) )
@http.route('/myATS/applicant/update_stage', type='json', auth='user')
def update_applicant_stage(self, applicant_id, stage_id, **kwargs):
try:
applicant = request.env['hr.applicant'].browse(int(applicant_id))
if applicant.exists():
applicant.write({'stage_id': int(stage_id)})
return {'success': True}
return {'success': False, 'error': 'Applicant not found'}
except Exception as e:
return {'success': False, 'error': str(e)}
@http.route('/myATS/job/create', type='http', auth='user', methods=['POST'], csrf=False) @http.route('/myATS/job/create', type='http', auth='user', methods=['POST'], csrf=False)
def create_job_request(self, **post): def create_job_request(self, **post):
try: try:

View File

@ -493,6 +493,71 @@
border: 1px solid var(--border-color) !important; border: 1px solid var(--border-color) !important;
box-shadow: 0 2px 5px var(--shadow-color) !important; box-shadow: 0 2px 5px var(--shadow-color) !important;
} }
/* Base button styling */
.btn-stage {
position: relative;
min-width: 100px;
padding: 0.5rem 1rem;
margin: 0 2px;
border-radius: 4px;
font-size: 0.85rem;
font-weight: 500;
text-align: center;
transition: all 0.25s ease;
cursor: pointer;
border: 1px solid #ddd;
outline: none;
}
/* Current stage styling */
.btn-stage-current {
background-color: #0d6efd; /* Primary blue */
color: white;
border-color: #0d6efd;
box-shadow: 0 2px 5px rgba(13, 110, 253, 0.3);
font-weight: 600;
}
/* Other stage options */
.btn-stage-option {
background-color: white;
color: #555;
border-color: #ddd;
}
/* Hover effects */
.btn-stage-option:hover {
background-color: #f0f7ff; /* Very light blue */
border-color: #0d6efd;
color: #0d6efd;
}
.btn-stage-current:hover {
background-color: #0b5ed7; /* Slightly darker blue */
}
/* Active state */
.btn-stage:active {
transform: translateY(1px);
}
/* Focus state */
.btn-stage:focus {
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.25);
}
/* Disabled state during loading */
.btn-stage.processing {
opacity: 0.7;
pointer-events: none;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.btn-stage {
min-width: 80px;
padding: 0.4rem 0.6rem;
font-size: 0.8rem;
margin: 2px;
}
}

View File

@ -248,20 +248,20 @@ function initApplicantsPage() {
}); });
} }
// Close modal when clicking outside of it // Close modal when clicking outside of it
applicantModal.addEventListener('click', function(e) { // applicantModal.addEventListener('click', function(e) {
if (e.target === applicantModal) { // if (e.target === applicantModal) {
applicantModal.classList.remove('show'); // applicantModal.classList.remove('show');
setTimeout(() => { // setTimeout(() => {
applicantModal.style.display = 'none'; // applicantModal.style.display = 'none';
}, 300); // }, 300);
document.body.style.overflow = ''; // document.body.style.overflow = '';
} // }
}); // });
// File Upload Handling // File Upload Handling
const resumeUpload = document.getElementById('resume-upload'); const resumeUpload = document.getElementById('resume-upload');
const resumeDropzone = document.getElementById('resume-dropzone'); const resumeDropzone = document.getElementById('resume-dropzone');
const resumePreview = document.getElementById('resume-preview'); const resumePreview = document.getElementById('resume-preview');
const resumePlaceholder = resumePreview.querySelector('.resume-preview-placeholder'); const resumePlaceholder = document.querySelector('.resume-preview-placeholder');
const resumeIframe = document.getElementById('resume-iframe'); const resumeIframe = document.getElementById('resume-iframe');
const resumeImage = document.getElementById('resume-image'); const resumeImage = document.getElementById('resume-image');
const unsupportedFormat = document.getElementById('unsupported-format'); const unsupportedFormat = document.getElementById('unsupported-format');

View File

@ -5,7 +5,6 @@ document.addEventListener("DOMContentLoaded", function () {
initNavigation(); initNavigation();
// Load default page based on URL hash or default to jobs // Load default page based on URL hash or default to jobs
loadPage(window.location.hash || "#jobs");
}); });
/** /**
@ -47,6 +46,61 @@ function initTheme() {
applyTheme(currentTheme === 'dark' ? 'light' : 'dark'); applyTheme(currentTheme === 'dark' ? 'light' : 'dark');
}); });
} }
document.querySelectorAll('.btn-stage').forEach(button => {
button.addEventListener('click', function() {
const container = this.closest('.stage-selector');
const buttons = container.querySelectorAll('.btn-stage');
const applicantId = container.dataset.applicantId;
const newStageId = this.dataset.stageId;
// Visual feedback
buttons.forEach(btn => {
btn.classList.remove('btn-stage-current');
btn.classList.add('btn-stage-option');
});
this.classList.remove('btn-stage-option');
this.classList.add('btn-stage-current', 'processing');
// AJAX call to update stage
fetch('/update_stage', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': getCSRFToken()
},
body: JSON.stringify({
applicant_id: applicantId,
stage_id: newStageId
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
showNotification('Stage updated successfully!', 'success');
} else {
throw new Error(data.error || 'Update failed');
}
})
.catch(error => {
console.error("Error:", error);
showNotification('Failed to update stage', 'danger');
// Revert visual state if needed
})
.finally(() => {
this.classList.remove('processing');
});
});
});
function getCSRFToken() {
return document.querySelector('meta[name="csrf-token"]').content;
}
function showNotification(message, type) {
// Your notification implementation
}
// Watch for system theme changes // Watch for system theme changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
@ -171,4 +225,5 @@ function initNavigation() {
// Initial highlight // Initial highlight
highlightActiveMenu(); highlightActiveMenu();
} }

View File

@ -118,7 +118,7 @@ function initCandidatesPage() {
const resumeUpload = document.getElementById('resume-upload'); const resumeUpload = document.getElementById('resume-upload');
const resumeDropzone = document.getElementById('resume-dropzone'); const resumeDropzone = document.getElementById('resume-dropzone');
const resumePreview = document.getElementById('resume-preview'); const resumePreview = document.getElementById('resume-preview');
const resumePlaceholder = resumePreview.querySelector('.resume-preview-placeholder'); const resumePlaceholder = document.querySelector('.resume-preview-placeholder');
const resumeIframe = document.getElementById('resume-iframe'); const resumeIframe = document.getElementById('resume-iframe');
const resumeImage = document.getElementById('resume-image'); const resumeImage = document.getElementById('resume-image');
const unsupportedFormat = document.getElementById('unsupported-format'); const unsupportedFormat = document.getElementById('unsupported-format');
@ -161,15 +161,15 @@ function initCandidatesPage() {
}); });
} }
candidateModal.addEventListener('click', function(e) { // candidateModal.addEventListener('click', function(e) {
if (e.target === candidateModal) { // if (e.target === candidateModal) {
candidateModal.classList.remove('show'); // candidateModal.classList.remove('show');
setTimeout(() => { // setTimeout(() => {
candidateModal.style.display = 'none'; // candidateModal.style.display = 'none';
}, 300); // }, 300);
document.body.style.overflow = ''; // document.body.style.overflow = '';
} // }
}); // });
function formatUserOption(user) { function formatUserOption(user) {
if (!user.id) return user.text; if (!user.id) return user.text;

View File

@ -1,5 +1,3 @@
/** @odoo-module */
// Define all your page initialization functions first // Define all your page initialization functions first
function initJobListPage() { function initJobListPage() {
console.log("Job List Page JS Loaded"); console.log("Job List Page JS Loaded");

View File

@ -243,6 +243,16 @@
<span t-esc="applicant.current_location or 'Location not specified'"/> <span t-esc="applicant.current_location or 'Location not specified'"/>
</span> </span>
</div> </div>
<div class="stage-selector btn-group" role="group" t-att-data-applicant-id="applicant.id">
<t t-foreach="applicant.hr_job_recruitment.recruitment_stage_ids" t-as="stage">
<button type="button"
class="btn btn-stage"
t-att-class="'btn btn-stage ' +
('btn-stage-current' if applicant.stage_id.id == stage.id else 'btn-stage-option')"
t-att-data-stage-id="stage.id"
t-esc="stage.display_name"/>
</t>
</div>
</div> </div>
<div class="ats-avatar"> <div class="ats-avatar">
<div class="avatar-wrapper"> <div class="avatar-wrapper">

View File

@ -28,13 +28,10 @@
<script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/ats.js"></script> <script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/ats.js"></script>
<!-- <script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/candidates.js"></script>--> <!-- <script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/candidates.js"></script>-->
<script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/job_requests.js?v=20"></script> <script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/job_requests.js?v=20"></script>
<script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/applicants.js?v=8"></script> <script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/applicants.js?v=10"></script>
<script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/candidates.js?v=6"></script> <script type="text/javascript" src="/hr_recruitment_web_app/static/src/js/candidates.js?v=6"></script>
<script type="text/javascript" <script type="text/javascript"
src="https://cdn.ckeditor.com/ckeditor5/39.0.0/classic/ckeditor.js"></script> src="https://cdn.ckeditor.com/ckeditor5/39.0.0/classic/ckeditor.js"></script>
<link rel="stylesheet" href="/hr_recruitment_web_app/static/src/css/select2.min.css"/>
<script type="text/javascript"
src="/hr_recruitment_web_app/static/src/js/select2.main.js"></script>
</head> </head>
<body class="ats-app"> <body class="ats-app">
<div class="layout-container"> <div class="layout-container">