Merge pull request 'frotnedn and bnackend crashing check' (#31) from RELIMIt into main
Deploy to S3 / deploy (push) Successful in 39s Details

Reviewed-on: #31
pull/32/head^2
ahmed.mujtaba 2026-08-28 13:23:38 +00:00
commit 8c55b17919
3 changed files with 18 additions and 27 deletions

View File

@ -42,7 +42,7 @@ import { companies, fmtDate, moneyK, pick } from '../data/seed'
/* Workflow order: learn (Overview, Resume, Documents) interview (Interview, /* Workflow order: learn (Overview, Resume, Documents) interview (Interview,
Forms, Feedback) track (Notes, Activity) audit (Timeline, History). */ Forms, Feedback) track (Notes, Activity) audit (Timeline, History). */
const TABS = ['Overview', 'Resume', 'Documents', 'Interview', 'Forms', 'Feedback', 'Notes', 'Activity', 'Timeline', 'History'] const TABS = ['Overview', 'Resume', 'Interview', 'Forms', 'Feedback', 'Notes', 'Activity', 'Timeline', 'History']
// Forward progression for the live Advance button. Rejected has no next stage. // Forward progression for the live Advance button. Rejected has no next stage.
const KANBAN_ORDER = ['Shortlist', 'Screening', 'Assessment', 'Interview', 'Offer', 'Hired'] const KANBAN_ORDER = ['Shortlist', 'Screening', 'Assessment', 'Interview', 'Offer', 'Hired']
const LABEL = { fontSize: 12, color: 'var(--text-3)', fontWeight: 600, textTransform: 'uppercase', marginBottom: 8 } const LABEL = { fontSize: 12, color: 'var(--text-3)', fontWeight: 600, textTransform: 'uppercase', marginBottom: 8 }
@ -673,20 +673,13 @@ export default function CandidateProfile({
function ResumeTab({ live }) { function ResumeTab({ live }) {
const source = live.documents?.[0]?.name const source = live.documents?.[0]?.name
const resumeKey = s3Api.resumeKeyFrom(live) const resumeKey = s3Api.resumeKeyFrom(live)
if (!live.resume_text) { if (!s3Api.canOpen(resumeKey)) {
return ( return (
<> <EmptyState icon="file" title="No résumé on file">
{s3Api.canOpen(resumeKey) && ( {source
<div className="flex gap-8" style={{ flexWrap: 'wrap', marginBottom: 14 }}> ? `${source} is attached but is not stored in S3, so it cannot be opened here.`
<OpenResumeButton filePath={resumeKey} /> : 'This candidate applied without an attachment we could open.'}
</div> </EmptyState>
)}
<EmptyState icon="file" title="No résumé text">
{source
? `${source} is attached but has not been parsed yet — run the match to extract it.`
: 'This candidate applied without an attachment we could read.'}
</EmptyState>
</>
) )
} }
return ( return (
@ -694,15 +687,11 @@ function ResumeTab({ live }) {
<div className="card-body"> <div className="card-body">
<h3 style={{ marginBottom: 4 }}>{live.name}</h3> <h3 style={{ marginBottom: 4 }}>{live.name}</h3>
<p className="text-muted"> <p className="text-muted">
{source ? `Extracted from ${source}` : 'Extracted from the application email'} {source ? `Original CV — ${source}` : 'Original CV from the application'}
</p> </p>
{s3Api.canOpen(resumeKey) && ( <div className="flex gap-8" style={{ flexWrap: 'wrap', margin: '10px 0 0' }}>
<div className="flex gap-8" style={{ flexWrap: 'wrap', margin: '10px 0 4px' }}> <OpenResumeButton filePath={resumeKey} />
<OpenResumeButton filePath={resumeKey} /> </div>
</div>
)}
<div className="divider" />
<div className="text-sm" style={{ whiteSpace: 'pre-wrap', lineHeight: 1.6 }}>{live.resume_text}</div>
</div> </div>
</div> </div>
) )

View File

@ -672,10 +672,12 @@ function MatchingWorkspace({
</div> </div>
)} )}
<div className="fw-600" style={{ marginBottom: 6 }}>Resume text</div> <div className="fw-600" style={{ marginBottom: 6 }}>CV</div>
<pre className="resume-thumb is-full"> {s3Api.canOpen(resumeKey) ? (
{resumeText || 'Resume text not extracted yet.'} <OpenResumeButton filePath={resumeKey} />
</pre> ) : (
<p className="text-muted text-sm">No CV file stored in S3 for this application.</p>
)}
</div> </div>
<div role="radiogroup" aria-label="Suggested roles" style={{ flex: '0 1 360px', minWidth: 260 }}> <div role="radiogroup" aria-label="Suggested roles" style={{ flex: '0 1 360px', minWidth: 260 }}>

View File

@ -270,7 +270,7 @@ export default function TalentPool() {
{c.aiScore != null && <ScoreChip score={c.aiScore} />} {c.aiScore != null && <ScoreChip score={c.aiScore} />}
</div> </div>
<div className="k-tags" style={{ marginBottom: 12 }}> <div className="k-tags" style={{ marginBottom: 12 }}>
{c.skills.slice(0, 4).map((s) => <span className="tag" key={s}>{s}</span>)} {(c.skills ?? []).slice(0, 4).map((s) => <span className="tag" key={s}>{s}</span>)}
</div> </div>
<div className="divider" style={{ margin: '12px 0' }} /> <div className="divider" style={{ margin: '12px 0' }} />
<div className="flex items-center" style={{ justifyContent: 'space-between' }}> <div className="flex items-center" style={{ justifyContent: 'space-between' }}>