-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApp.tsx
More file actions
112 lines (103 loc) 路 3.58 KB
/
Copy pathApp.tsx
File metadata and controls
112 lines (103 loc) 路 3.58 KB
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
import React, { useState, useCallback } from 'react';
import { InterviewStage, Candidate, Job, TranscriptEntry, Analysis } from './types';
import SetupScreen from './components/SetupScreen';
import PreInterviewScreen from './components/PreInterviewScreen';
import InterviewScreen from './components/InterviewScreen';
import PostInterviewAnalysis from './components/PostInterviewAnalysis';
import { analyzeTranscript } from './services/geminiService';
const App: React.FC = () => {
const [stage, setStage] = useState<InterviewStage>(InterviewStage.SETUP);
const [candidate, setCandidate] = useState<Candidate | null>(null);
const [job, setJob] = useState<Job | null>(null);
const [transcript, setTranscript] = useState<TranscriptEntry[]>([]);
const [analysis, setAnalysis] = useState<Analysis | null>(null);
const [recording, setRecording] = useState<Blob | null>(null);
const [error, setError] = useState<string | null>(null);
const handleSetupComplete = (newJob: Job, newCandidate: Candidate) => {
setJob(newJob);
setCandidate(newCandidate);
setStage(InterviewStage.PRE_INTERVIEW);
};
const handleStartInterview = () => {
setStage(InterviewStage.IN_INTERVIEW);
};
const handleInterviewEnd = useCallback(async (finalTranscript: TranscriptEntry[], emotionData: string, rec: Blob | null) => {
if (!candidate || !job) {
setError("Candidate or Job data is missing.");
setStage(InterviewStage.ANALYSIS);
return;
}
setTranscript(finalTranscript);
setRecording(rec);
setStage(InterviewStage.ANALYSIS);
setError(null);
try {
const result = await analyzeTranscript(finalTranscript, candidate, job, emotionData);
setAnalysis(result);
} catch (err) {
console.error("Analysis failed:", err);
setError("Failed to analyze the interview transcript. Please try again.");
}
}, [candidate, job]);
const handleRestart = () => {
setStage(InterviewStage.SETUP);
setCandidate(null);
setJob(null);
setTranscript([]);
setAnalysis(null);
setRecording(null);
setError(null);
}
const renderStage = () => {
switch (stage) {
case InterviewStage.SETUP:
return (
<SetupScreen onSetupComplete={handleSetupComplete} />
);
case InterviewStage.PRE_INTERVIEW:
if (!candidate || !job) {
// This should not happen in the normal flow
return <div className="text-center">Loading...</div>;
}
return (
<PreInterviewScreen
candidate={candidate}
job={job}
onStart={handleStartInterview}
/>
);
case InterviewStage.IN_INTERVIEW:
if (!candidate || !job) {
// This should not happen in the normal flow
return <div className="text-center">Error: Missing interview context. Please restart.</div>;
}
return (
<InterviewScreen
candidate={candidate}
job={job}
onInterviewEnd={handleInterviewEnd}
/>
);
case InterviewStage.ANALYSIS:
return (
<PostInterviewAnalysis
analysis={analysis}
transcript={transcript}
error={error}
onRestart={handleRestart}
recording={recording}
/>
);
default:
return <div>Invalid stage</div>;
}
};
return (
<div className="min-h-screen bg-gray-900 text-white flex flex-col items-center justify-center p-4 font-sans">
<div className="w-full max-w-5xl mx-auto">
{renderStage()}
</div>
</div>
);
};
export default App;