@@ -3204,12 +3204,13 @@ <h5 class="modal-title" id="jobDetailTitle"><i class="fas fa-briefcase me-2" sty
32043204 candidatePhone : dbInt . candidate_phone || '' ,
32053205 position : dbInt . interview_role || 'Position' ,
32063206 round : dbInt . interview_level || 'Round' ,
3207- date : dbInt . completed_at ? dbInt . completed_at . split ( 'T' ) [ 0 ] :
3208- dbInt . created_at ? dbInt . created_at . split ( 'T' ) [ 0 ] : new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ,
3209- startTime : dbInt . started_at ? new Date ( dbInt . started_at ) . toTimeString ( ) . slice ( 0 , 5 ) : '10:00' ,
3210- endTime : dbInt . completed_at ? new Date ( dbInt . completed_at ) . toTimeString ( ) . slice ( 0 , 5 ) : '10:45' ,
3211- interviewer : dbInt . interview_type === 'ai_voice' ? 'AI Interviewer' : 'Recruiting Team' ,
3212- mode : dbInt . interview_type === 'ai_voice' ? 'proctored' : 'video' ,
3207+ date : dbInt . scheduled_date || ( dbInt . completed_at ? dbInt . completed_at . split ( 'T' ) [ 0 ] :
3208+ dbInt . created_at ? dbInt . created_at . split ( 'T' ) [ 0 ] : new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ) ,
3209+ startTime : dbInt . scheduled_time || ( dbInt . started_at ? new Date ( dbInt . started_at ) . toTimeString ( ) . slice ( 0 , 5 ) : '10:00' ) ,
3210+ endTime : dbInt . scheduled_end_time || ( dbInt . completed_at ? new Date ( dbInt . completed_at ) . toTimeString ( ) . slice ( 0 , 5 ) : '10:45' ) ,
3211+ interviewer : dbInt . interviewer_name || ( dbInt . interview_type === 'ai_voice' ? 'AI Interviewer' : 'Recruiting Team' ) ,
3212+ interviewerEmail : dbInt . interviewer_email || '' ,
3213+ mode : dbInt . interview_mode || ( dbInt . interview_type === 'ai_voice' ? 'proctored' : 'video' ) ,
32133214 status : dbInt . status === 'pending' ? 'scheduled' : ( dbInt . status || 'scheduled' ) ,
32143215 token : dbInt . token || '' ,
32153216 job_id : dbInt . job_id ,
@@ -3221,7 +3222,9 @@ <h5 class="modal-title" id="jobDetailTitle"><i class="fas fa-briefcase me-2" sty
32213222 completedAt : dbInt . completed_at || null ,
32223223 conversationLog : dbInt . conversation_log || null ,
32233224 notificationLog : dbInt . notification_log || [ ] ,
3224- proctorSettings : dbInt . proctor_settings || null
3225+ proctorSettings : dbInt . proctor_settings || null ,
3226+ meetingLink : dbInt . meeting_link || '' ,
3227+ notes : dbInt . notes || ''
32253228 } ;
32263229 } ) ;
32273230 // DEDUP: Remove duplicate interview records (keep first = newest by created_at)
@@ -4165,6 +4168,7 @@ <h3>${stats.tokenLinksGenerated}</h3>
41654168 <button class="btn-sm-action view" title="Details" onclick="viewInterview('${ int . id } ')"><i class="fas fa-eye"></i></button>
41664169 <button class="btn-sm-action notify" title="Send Notification" onclick="openSendNotifModal('${ int . id } ')"><i class="fas fa-paper-plane"></i></button>
41674170 ${ int . mode === 'proctored' ? `<button class="btn-sm-action" style="background:#ede9fe;color:#7c3aed;" title="Proctor Settings" onclick="viewProctorSettings('${ int . id } ')"><i class="fas fa-shield-halved"></i></button>` : '' }
4171+ <button class="btn-sm-action" style="background:#d1fae5;color:#065f46;" title="Mark Completed" onclick="markInterviewCompleted('${ int . id } ')"><i class="fas fa-check"></i></button>
41684172 <button class="btn-sm-action delete" title="Cancel" onclick="cancelInterview('${ int . id } ')"><i class="fas fa-xmark"></i></button>
41694173 </td>
41704174 </tr>
@@ -4457,11 +4461,18 @@ <h3>${stats.tokenLinksGenerated}</h3>
44574461}
44584462
44594463function switchInterviewTab ( tabName , el ) {
4460- document . querySelectorAll ( '.tab-content' ) . forEach ( t => t . classList . remove ( 'active' ) ) ;
4461- document . querySelectorAll ( '.custom-tab' ) . forEach ( t => t . classList . remove ( 'active' ) ) ;
4464+ document . querySelectorAll ( '#section-interviews .tab-content' ) . forEach ( t => t . classList . remove ( 'active' ) ) ;
4465+ document . querySelectorAll ( '#section-interviews .custom-tab' ) . forEach ( t => t . classList . remove ( 'active' ) ) ;
44624466 const tab = document . getElementById ( 'interviewTab-' + tabName ) ;
44634467 if ( tab ) tab . classList . add ( 'active' ) ;
44644468 if ( el ) el . classList . add ( 'active' ) ;
4469+ // Re-render the active tab's data to ensure fresh results are shown
4470+ if ( tabName === 'completed' ) renderCompletedInterviewTable ( ) ;
4471+ else if ( tabName === 'cancelled' ) renderCancelledInterviewTable ( ) ;
4472+ else if ( tabName === 'proctored' ) renderProctoredTable ( ) ;
4473+ else if ( tabName === 'results' ) renderResultsTable ( ) ;
4474+ else if ( tabName === '360interview' ) render360InterviewResults ( ) ;
4475+ else if ( tabName === 'upcoming' ) renderInterviewTable ( ) ;
44654476}
44664477
44674478// ===== HANDLE CREATE JOB =====
@@ -4716,6 +4727,7 @@ <h3>${stats.tokenLinksGenerated}</h3>
47164727 interview_role : position ,
47174728 interview_level : round ,
47184729 interview_type : ( mode === 'proctored' || mode === 'proctored_360' ) ? 'ai_voice' : 'human_live' ,
4730+ interview_mode : mode ,
47194731 token_type : ( mode === 'proctored' || mode === 'proctored_360' ) ? 'shortlist' : 'custom' ,
47204732 token,
47214733 status : ( mode === 'proctored' || mode === 'proctored_360' ) ? 'pending' : 'scheduled' ,
@@ -4727,7 +4739,14 @@ <h3>${stats.tokenLinksGenerated}</h3>
47274739 question_count : parseInt ( document . getElementById ( 'intQuestionCount' ) ?. value ) || 6 ,
47284740 max_attempts : 1 ,
47294741 interview_language : language ,
4730- experience_level : experienceLevel
4742+ experience_level : experienceLevel ,
4743+ scheduled_date : date ,
4744+ scheduled_time : startTime ,
4745+ scheduled_end_time : endTime ,
4746+ interviewer_name : interviewer ,
4747+ interviewer_email : interviewerEmail || '' ,
4748+ meeting_link : meetingLink || '' ,
4749+ notes : notes || ''
47314750 } ;
47324751
47334752 // Local Payload for immediate UI rendering (camelCase API expectations)
@@ -4780,6 +4799,7 @@ <h3>${stats.tokenLinksGenerated}</h3>
47804799 renderCancelledInterviewTable ( ) ;
47814800 renderProctoredTable ( ) ;
47824801 render360InterviewResults ( ) ;
4802+ renderResultsTable ( ) ;
47834803 renderDashboardStats ( ) ;
47844804 renderDashboardInterviews ( ) ;
47854805 renderDashboardActivities ( ) ;
@@ -5271,8 +5291,9 @@ <h6 style="color:var(--text-primary);margin-bottom:4px;">No Applications Yet</h6
52715291 showToast ( '🗑️ Job posting deleted' ) ;
52725292}
52735293
5274- function cancelInterview ( id ) {
5294+ async function cancelInterview ( id ) {
52755295 if ( ! confirm ( 'Cancel this interview?' ) ) return ;
5296+ const int = appData . interviews . find ( i => i . id === id ) ;
52765297 DataStore . update ( data => {
52775298 const interview = data . interviews . find ( i => i . id === id ) ;
52785299 if ( interview ) {
@@ -5291,10 +5312,68 @@ <h6 style="color:var(--text-primary);margin-bottom:4px;">No Applications Yet</h6
52915312 renderCancelledInterviewTable ( ) ;
52925313 renderProctoredTable ( ) ;
52935314 render360InterviewResults ( ) ;
5315+ renderResultsTable ( ) ;
52945316 renderDashboardStats ( ) ;
52955317 renderDashboardActivities ( ) ;
52965318 updateInterviewCounts ( ) ;
52975319 showToast ( 'Interview cancelled' ) ;
5320+
5321+ // Persist cancellation to Supabase
5322+ try {
5323+ const db = ( typeof getSupabaseClient === 'function' ? getSupabaseClient ( ) : null ) || window . SimpaticoDB || window . _supabaseClient ;
5324+ if ( db && int ?. id ) {
5325+ const { error } = await db . from ( 'interviews' ) . update ( { status : 'cancelled' } ) . eq ( 'id' , int . id ) ;
5326+ if ( error ) console . warn ( '[cancel] DB update error:' , error . message ) ;
5327+ else console . log ( '[cancel] ✅ Interview cancelled in DB:' , int . id ) ;
5328+ }
5329+ } catch ( e ) {
5330+ console . warn ( '[cancel] DB persist failed:' , e . message ) ;
5331+ }
5332+ }
5333+
5334+ async function markInterviewCompleted ( id ) {
5335+ if ( ! confirm ( 'Mark this interview as completed?' ) ) return ;
5336+ const int = appData . interviews . find ( i => i . id === id ) ;
5337+ DataStore . update ( data => {
5338+ const interview = data . interviews . find ( i => i . id === id ) ;
5339+ if ( interview ) {
5340+ interview . status = 'completed' ;
5341+ interview . completedAt = new Date ( ) . toISOString ( ) ;
5342+ data . activities . unshift ( {
5343+ type : 'interview' ,
5344+ title : `Interview Completed: ${ interview . candidateName } ` ,
5345+ description : `${ interview . position } · ${ interview . round } · Marked completed by HR` ,
5346+ timestamp : Date . now ( )
5347+ } ) ;
5348+ }
5349+ } ) ;
5350+ appData = DataStore . get ( ) ;
5351+ renderInterviewTable ( ) ;
5352+ renderCompletedInterviewTable ( ) ;
5353+ renderCancelledInterviewTable ( ) ;
5354+ renderProctoredTable ( ) ;
5355+ render360InterviewResults ( ) ;
5356+ renderResultsTable ( ) ;
5357+ renderDashboardStats ( ) ;
5358+ renderDashboardInterviews ( ) ;
5359+ renderDashboardActivities ( ) ;
5360+ updateInterviewCounts ( ) ;
5361+ showToast ( '✅ Interview marked as completed' ) ;
5362+
5363+ // Persist to Supabase
5364+ try {
5365+ const db = ( typeof getSupabaseClient === 'function' ? getSupabaseClient ( ) : null ) || window . SimpaticoDB || window . _supabaseClient ;
5366+ if ( db && int ?. id ) {
5367+ const { error } = await db . from ( 'interviews' ) . update ( {
5368+ status : 'completed' ,
5369+ completed_at : new Date ( ) . toISOString ( )
5370+ } ) . eq ( 'id' , int . id ) ;
5371+ if ( error ) console . warn ( '[complete] DB update error:' , error . message ) ;
5372+ else console . log ( '[complete] ✅ Interview marked completed in DB:' , int . id ) ;
5373+ }
5374+ } catch ( e ) {
5375+ console . warn ( '[complete] DB persist failed:' , e . message ) ;
5376+ }
52985377}
52995378
53005379function viewProctorSettings ( id ) {
0 commit comments