diff --git a/web/src/components/InterviewCard.vue b/web/src/components/InterviewCard.vue index 0e16961..358fb7b 100644 --- a/web/src/components/InterviewCard.vue +++ b/web/src/components/InterviewCard.vue @@ -55,6 +55,42 @@ async function dismissSignal(sig: StageSignal) { await useApiFetch(`/api/stage-signals/${sig.id}/dismiss`, { method: 'POST' }) } +const bodyExpanded = ref(false) + +// Re-classify chips — neutral triggers two-call dismiss path +const RECLASSIFY_CHIPS = [ + { label: '🟡 Interview', value: 'interview_scheduled' as const }, + { label: '✅ Positive', value: 'positive_response' as const }, + { label: '🟢 Offer', value: 'offer_received' as const }, + { label: '📋 Survey', value: 'survey_received' as const }, + { label: '✖ Rejected', value: 'rejected' as const }, + { label: '— Neutral', value: 'neutral' }, +] as const + +async function reclassifySignal(sig: StageSignal, newLabel: string) { + if (newLabel === 'neutral') { + // Optimistic removal — neutral signals are dismissed + const arr = props.job.stage_signals + const idx = arr.findIndex(s => s.id === sig.id) + if (idx !== -1) arr.splice(idx, 1) + // Two-call path: persist corrected label then dismiss (Avocet training hook) + await useApiFetch(`/api/stage-signals/${sig.id}/reclassify`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ stage_signal: 'neutral' }), + }) + await useApiFetch(`/api/stage-signals/${sig.id}/dismiss`, { method: 'POST' }) + } else { + // Optimistic local re-label — Vue 3 proxy tracks the mutation + sig.stage_signal = newLabel as StageSignal['stage_signal'] + await useApiFetch(`/api/stage-signals/${sig.id}/reclassify`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ stage_signal: newLabel }), + }) + } +} + const scoreClass = computed(() => { const s = (props.job.match_score ?? 0) * 100 if (s >= 85) return 'score--high' @@ -138,21 +174,42 @@ const columnColor = computed(() => { borderTopColor: COLOR_BORDER[SIGNAL_META[sig.stage_signal].color], }" > - - 📧 Email suggests: {{ SIGNAL_META[sig.stage_signal].label }} - - {{ sig.subject.slice(0, 60) }}{{ sig.subject.length > 60 ? '…' : '' }} -
- - +
+ + 📧 {{ SIGNAL_META[sig.stage_signal].label.replace('Move to ', '') }} + + {{ sig.subject.slice(0, 60) }}{{ sig.subject.length > 60 ? '…' : '' }} +
+ + + +
+
+ +
+
From: {{ sig.from_addr }}
+
{{ sig.body }}
+
No email body available.
+
+ Re-classify: + +