File size: 5,185 Bytes
57303cc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { useState, useEffect } from 'react'
import { useParams, useNavigate } from 'react-router-dom'

export default function BriefPreview() {
  const { candidateId } = useParams()
  const navigate = useNavigate()
  const [brief, setBrief] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')

  useEffect(() => {
    async function fetchBrief() {
      try {
        const res = await fetch(`/api/candidates/${candidateId}/brief`)
        if (!res.ok) {
          const errData = await res.json()
          throw new Error(errData.detail || 'Failed to fetch brief.')
        }
        const data = await res.json()
        setBrief(data)
      } catch (err) {
        console.error(err)
        setError(err.message || 'Could not load prep brief.')
      } finally {
        setLoading(false)
      }
    }
    fetchBrief()
  }, [candidateId])

  const handlePrint = () => {
    window.print()
  }

  if (loading) {
    return <div className="loading">Generating prep brief...</div>
  }

  if (error) {
    return (
      <div className="card">
        <h2 className="status-warning">โš ๏ธ Error</h2>
        <p>{error}</p>
        <button className="btn btn-secondary" style={{ marginTop: 12 }} onClick={() => navigate('/score')}>
          Back to Scoring
        </button>
      </div>
    )
  }

  if (!brief) return null

  return (
    <>
      <div className="no-print" style={{ marginBottom: 16, display: 'flex', gap: 12 }}>
        <button className="btn btn-secondary" onClick={() => navigate('/score')}>
          โ† Back to Scoring
        </button>
        <button className="btn btn-success" onClick={handlePrint}>
          ๐Ÿ–จ๏ธ Print Prep Brief
        </button>
      </div>

      <div className="card brief-card" style={{ borderTop: '6px solid var(--accent)' }}>
        <div className="brief-header">
          <span className="badge badge-consulting" style={{ marginBottom: 8 }}>
            {brief.client_archetype === 'consulting' ? '๐Ÿ’ผ Corporate Vetting Profile' : '๐Ÿš€ Startup Vetting Profile'}
          </span>
          <h1>Candidate Interview Preparation Brief</h1>
          <p style={{ color: 'var(--text-muted)' }}>
            Prepared for <strong>{brief.candidate_name}</strong> for their interview with <strong>{brief.client_name}</strong>
          </p>
        </div>

        <hr style={{ border: '0', borderTop: '1px solid var(--border)', margin: '20px 0' }} />

        <div className="form-group">
          <strong>Client Expectations:</strong>
          <p style={{ background: '#f8f9fa', padding: 12, borderRadius: 'var(--radius)', border: '1px solid var(--border)', marginTop: 8 }}>
            {brief.client_expectations || 'No specific custom expectations logged.'}
          </p>
        </div>

        <div style={{ marginTop: 24 }}>
          <h3>Competency Alignment Check</h3>
          <table className="table" style={{ marginTop: 8 }}>
            <thead>
              <tr>
                <th>Competency</th>
                <th>Candidate Score</th>
                <th>Min. Required</th>
                <th>Status</th>
              </tr>
            </thead>
            <tbody>
              {brief.competency_scores.map((comp) => (
                <tr key={comp.name}>
                  <td><strong>{comp.name}</strong></td>
                  <td>{comp.score} / 5</td>
                  <td>{comp.min_required} / 5</td>
                  <td className={comp.status === 'pass' ? 'status-pass' : 'status-warning'}>
                    {comp.status === 'pass' ? 'โœ“ Meets Expectations' : 'โš ๏ธ Gap Identified'}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        <div style={{ marginTop: 28 }}>
          <h3 style={{ color: 'var(--accent)' }}>๐Ÿ’ก Tailored Vetting Coaching & Strategy</h3>
          <p style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginBottom: 12 }}>
            Prioritized tips targeting areas of potential client mismatch:
          </p>
          <ul style={{ paddingLeft: 20, lineHeight: 1.7 }}>
            {brief.coaching_tips.map((tip, idx) => (
              <li key={idx} style={{ marginBottom: 10 }}>
                {tip}
              </li>
            ))}
          </ul>
        </div>

        <div style={{ marginTop: 28 }}>
          <h3>๐ŸŽฏ High-Probability Practice Questions</h3>
          <p style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginBottom: 12 }}>
            Have the candidate practice the STAR method with these archetype-relevant questions:
          </p>
          <ul style={{ paddingLeft: 20, lineHeight: 1.7 }}>
            {brief.practice_questions.map((q, idx) => (
              <li key={idx} style={{ marginBottom: 10, fontStyle: 'italic' }}>
                "{q}"
              </li>
            ))}
          </ul>
        </div>

        <div className="no-print" style={{ marginTop: 32, fontSize: '0.8rem', color: 'var(--text-muted)', textAlign: 'center' }}>
          Generated via Staffinc Match on {new Date(brief.generated_at).toLocaleString()}
        </div>
      </div>
    </>
  )
}