Skip to content

Commit c79bff2

Browse files
committed
update frontend
1 parent 22ee349 commit c79bff2

File tree

4 files changed

+39
-121
lines changed

4 files changed

+39
-121
lines changed

frontend/src/components/ApplicationList.tsx

Lines changed: 11 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@ import React, { useState } from 'react';
22
import { Button } from '@mui/material';
33
import {
44
Visibility as VisibilityIcon,
5-
Chat as ChatIcon,
6-
Assessment as AssessmentIcon
5+
Chat as ChatIcon
76
} from '@mui/icons-material';
87
import type { Application, SortField, SortDirection } from '../types/dashboard';
9-
import { isHrUser, getValidToken } from '../utils/auth';
8+
import { isHrUser } from '../utils/auth';
109
import ChatHistoryModal from './modals/ChatHistoryModal';
1110
import CandidateChatModal from './modals/CandidateChatModal';
12-
import apiConfig from '../utils/api';
1311

1412
interface ApplicationListProps {
1513
applications: Application[];
@@ -29,68 +27,11 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
2927
onSort,
3028
onStatusClick,
3129
onHrDecisionClick,
32-
onDetailsClick,
33-
onRefreshApplications
30+
onDetailsClick
3431
}) => {
3532
const [isChatHistoryModalOpen, setIsChatHistoryModalOpen] = useState(false);
3633
const [isCandidateChatModalOpen, setIsCandidateChatModalOpen] = useState(false);
3734
const [selectedChatApplication, setSelectedChatApplication] = useState<Application | null>(null);
38-
39-
const [scoringApplications, setScoringApplications] = useState<Set<string>>(new Set());
40-
41-
const triggerManualScoring = async (application: Application) => {
42-
const token = getValidToken();
43-
if (!token) {
44-
alert('Please login again to trigger scoring.');
45-
return;
46-
}
47-
48-
const applicationId = application.applicationId || application.application_id;
49-
if (!applicationId) {
50-
alert('No application ID found');
51-
return;
52-
}
53-
setScoringApplications(prev => new Set(prev).add(applicationId));
54-
55-
try {
56-
console.log('Triggering manual interview scoring for application:', applicationId);
57-
58-
const response = await fetch(apiConfig.getFullURL(`/api/v1/applications/${applicationId}/assessment/interview/trigger`), {
59-
method: 'POST',
60-
headers: {
61-
'Authorization': `Bearer ${token}`,
62-
'Content-Type': 'application/json'
63-
},
64-
credentials: 'include'
65-
});
66-
67-
if (response.ok) {
68-
const data = await response.json();
69-
if (data.success) {
70-
alert('Interview scoring triggered successfully! Scores will be updated shortly.');
71-
if (onRefreshApplications) {
72-
setTimeout(() => {
73-
onRefreshApplications();
74-
}, 2000); // Give server time to process scoring
75-
}
76-
} else {
77-
alert(data.message || 'Failed to trigger scoring');
78-
}
79-
} else {
80-
const errorData = await response.json().catch(() => ({}));
81-
alert(errorData.message || `Failed to trigger scoring (${response.status})`);
82-
}
83-
} catch (error) {
84-
console.error('Error triggering manual scoring:', error);
85-
alert('Error triggering scoring. Please try again.');
86-
} finally {
87-
setScoringApplications(prev => {
88-
const newSet = new Set(prev);
89-
newSet.delete(applicationId);
90-
return newSet;
91-
});
92-
}
93-
};
9435

9536
const getSortIcon = (field: SortField): string => {
9637
if (sortField !== field) return '';
@@ -242,19 +183,9 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
242183
>
243184
INTERVIEW {getSortIcon('chatScore')}
244185
</div>
245-
<div
246-
className="final-score-header sortable"
247-
onClick={() => onSort('finalScore')}
248-
onKeyDown={(e) => e.key === 'Enter' && onSort('finalScore')}
249-
role="button"
250-
tabIndex={0}
251-
style={{ flexBasis: '8%' }}
252-
>
253-
FINAL {getSortIcon('finalScore')}
254-
</div>
255186
<div
256187
className="interview-comment-header"
257-
style={{ flexBasis: '12%' }}
188+
style={{ flexBasis: '14%' }}
258189
>
259190
RECOMMENDATION
260191
</div>
@@ -264,19 +195,19 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
264195
onKeyDown={(e) => e.key === 'Enter' && onSort('hrDecision')}
265196
role="button"
266197
tabIndex={0}
267-
style={{ flexBasis: '10%' }}
198+
style={{ flexBasis: '12%' }}
268199
>
269200
HR DECISION {getSortIcon('hrDecision')}
270201
</div>
271202
<div
272203
className="details-header"
273-
style={{ flexBasis: '12%' }}
204+
style={{ flexBasis: '14%' }}
274205
>
275206
DETAILS
276207
</div>
277208
<div
278209
className="chat-header"
279-
style={{ flexBasis: '14%' }}
210+
style={{ flexBasis: '16%' }}
280211
>
281212
CHAT
282213
</div>
@@ -361,39 +292,7 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
361292
</div>
362293
</div>
363294

364-
<div className="final-score" style={{ flexBasis: '8%' }}>
365-
<div style={{ fontSize: '12px', textAlign: 'center' }}>
366-
{(() => {
367-
const finalScore = application.assessment?.finalScore;
368-
return finalScore !== undefined && finalScore !== null ? (
369-
<span style={{ fontWeight: 'bold', color: '#2c3e50' }}>{finalScore}</span>
370-
) : (
371-
<span style={{ color: '#95a5a6' }}>-</span>
372-
);
373-
})()}
374-
{isHrUser() && (
375-
<Button
376-
variant="text"
377-
size="small"
378-
startIcon={<AssessmentIcon />}
379-
onClick={() => triggerManualScoring(application)}
380-
disabled={scoringApplications.has(application.applicationId || application.application_id || '')}
381-
sx={{
382-
textTransform: 'none',
383-
fontSize: '8px',
384-
minWidth: 'auto',
385-
mt: 0.5,
386-
p: 0.3,
387-
display: 'block'
388-
}}
389-
>
390-
{scoringApplications.has(application.applicationId || application.application_id || '') ? 'Scoring...' : 'Re-score'}
391-
</Button>
392-
)}
393-
</div>
394-
</div>
395-
396-
<div className="ai-recommend" style={{ flexBasis: '12%' }}>
295+
<div className="ai-recommend" style={{ flexBasis: '14%' }}>
397296
<div style={{ fontSize: '11px' }}>
398297
{(() => {
399298
// Check for both API formats
@@ -444,7 +343,7 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
444343
</div>
445344
</div>
446345

447-
<div className="hr-decision" style={{ flexBasis: '10%' }}>
346+
<div className="hr-decision" style={{ flexBasis: '12%' }}>
448347
<span
449348
className="status-badge clickable"
450349
style={{
@@ -463,7 +362,7 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
463362
</span>
464363
</div>
465364

466-
<div className="details" style={{ flexBasis: '12%' }}>
365+
<div className="details" style={{ flexBasis: '14%' }}>
467366
<Button
468367
variant="outlined"
469368
color="primary"
@@ -479,7 +378,7 @@ const ApplicationList: React.FC<ApplicationListProps> = ({
479378
</Button>
480379
</div>
481380

482-
<div className="chat" style={{ flexBasis: '14%' }}>
381+
<div className="chat" style={{ flexBasis: '16%' }}>
483382
<Button
484383
variant={isHrUser() ? 'outlined' : 'contained'}
485384
color={isHrUser() ? 'secondary' : 'primary'}

frontend/src/components/ApplicationsView.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ interface ApplicationsViewProps {
1212
onStatusClick: (application: Application) => void;
1313
onHrDecisionClick: (application: Application) => void;
1414
onDetailsClick: (application: Application) => void;
15-
onRefreshApplications: () => void;
1615
}
1716

1817
const ApplicationsView: React.FC<ApplicationsViewProps> = ({
@@ -23,8 +22,7 @@ const ApplicationsView: React.FC<ApplicationsViewProps> = ({
2322
onSort,
2423
onStatusClick,
2524
onHrDecisionClick,
26-
onDetailsClick,
27-
onRefreshApplications
25+
onDetailsClick
2826
}) => {
2927
if (isLoading) {
3028
return (
@@ -62,7 +60,6 @@ const ApplicationsView: React.FC<ApplicationsViewProps> = ({
6260
onStatusClick={onStatusClick}
6361
onHrDecisionClick={onHrDecisionClick}
6462
onDetailsClick={onDetailsClick}
65-
onRefreshApplications={onRefreshApplications}
6663
/>
6764
);
6865
};

frontend/src/components/Dashboard.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ const Dashboard: React.FC = () => {
141141
}
142142
};
143143

144-
const [selectedStatus] = useState<string>('ALL');
144+
const [selectedStatus, setSelectedStatus] = useState<string>('ALL');
145145
const [searchTerm, setSearchTerm] = useState<string>('');
146146
const [sortField, setSortField] = useState<SortField>('date');
147147
const [sortDirection, setSortDirection] = useState<SortDirection>('desc');
@@ -622,9 +622,11 @@ const Dashboard: React.FC = () => {
622622
<DashboardHeader
623623
selectedView={selectedView}
624624
searchTerm={searchTerm}
625+
selectedStatus={selectedStatus}
625626
resultsCount={filteredAndSortedApplications.length}
626627
onViewChange={setSelectedView}
627628
onSearchChange={setSearchTerm}
629+
onStatusChange={setSelectedStatus}
628630
onAddHrClick={() => setIsHrRegisterModalOpen(true)}
629631
onCreateJobClick={openCreateJobModal}
630632
/>
@@ -639,9 +641,6 @@ const Dashboard: React.FC = () => {
639641
onStatusClick={handleStatusClick}
640642
onHrDecisionClick={handleHrDecisionClick}
641643
onDetailsClick={handleDetailsClick}
642-
onRefreshApplications={() => {
643-
fetchApplications(currentPage, pageSize);
644-
}}
645644
/>
646645
)}
647646

frontend/src/components/DashboardHeader.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import {
88
Tabs,
99
Tab,
1010
Chip,
11-
TextField
11+
TextField,
12+
FormControl,
13+
InputLabel,
14+
Select,
15+
MenuItem
1216
} from '@mui/material';
1317
import {
1418
People as PeopleIcon,
@@ -24,19 +28,23 @@ import { logout } from '../utils/auth';
2428
interface DashboardHeaderProps {
2529
selectedView: ViewMode;
2630
searchTerm: string;
31+
selectedStatus: string;
2732
resultsCount: number;
2833
onViewChange: (view: ViewMode) => void;
2934
onSearchChange: (term: string) => void;
35+
onStatusChange: (status: string) => void;
3036
onAddHrClick: () => void;
3137
onCreateJobClick: () => void;
3238
}
3339

3440
const DashboardHeader: React.FC<DashboardHeaderProps> = ({
3541
selectedView,
3642
searchTerm,
43+
selectedStatus,
3744
resultsCount,
3845
onViewChange,
3946
onSearchChange,
47+
onStatusChange,
4048
onAddHrClick,
4149
onCreateJobClick
4250
}) => {
@@ -114,6 +122,21 @@ const DashboardHeader: React.FC<DashboardHeaderProps> = ({
114122
size="small"
115123
sx={{ minWidth: 300 }}
116124
/>
125+
{selectedView === 'applications' && (
126+
<FormControl size="small" sx={{ minWidth: 160 }}>
127+
<InputLabel>Filter by Status</InputLabel>
128+
<Select
129+
value={selectedStatus}
130+
onChange={(e) => onStatusChange(e.target.value)}
131+
label="Filter by Status"
132+
>
133+
<MenuItem value="ALL">All Statuses</MenuItem>
134+
<MenuItem value="AI_SCREENING">AI Screening</MenuItem>
135+
<MenuItem value="AI_INTERVIEW">AI Interview</MenuItem>
136+
<MenuItem value="COMPLETED">Completed</MenuItem>
137+
</Select>
138+
</FormControl>
139+
)}
117140
<Chip
118141
label={`${resultsCount} results`}
119142
color="default"

0 commit comments

Comments
 (0)