InterviewAI / src /context /InterviewContext.tsx
viraj-421's picture
Initial commit: AI-Powered Mock Interview Platform with Auth, Certificates, and Timer
a0da743
Raw History Blame Contribute Delete
5.66 kB
'use client';
import React, { createContext, useContext, useReducer, useCallback } from 'react';
import {
InterviewSession,
InterviewConfig,
Question,
ChatMessage,
Evaluation,
Answer,
SessionSummary,
} from '@/types/interview';
type InterviewAction =
| { type: 'START_SESSION'; payload: { config: InterviewConfig } }
| { type: 'SET_QUESTIONS'; payload: { questions: Question[] } }
| { type: 'ADD_MESSAGE'; payload: { message: ChatMessage } }
| { type: 'SUBMIT_ANSWER'; payload: { answer: Answer } }
| { type: 'ADD_EVALUATION'; payload: { evaluation: Evaluation } }
| { type: 'NEXT_QUESTION' }
| { type: 'SET_STATUS'; payload: { status: InterviewSession['status'] } }
| { type: 'COMPLETE_SESSION'; payload: { summary: SessionSummary } }
| { type: 'RESET_SESSION' };
interface InterviewState {
session: InterviewSession | null;
}
const initialState: InterviewState = {
session: null,
};
function generateId(): string {
return Date.now().toString(36) + Math.random().toString(36).substring(2);
}
function interviewReducer(state: InterviewState, action: InterviewAction): InterviewState {
switch (action.type) {
case 'START_SESSION':
return {
session: {
id: generateId(),
config: action.payload.config,
questions: [],
answers: [],
evaluations: [],
messages: [],
currentQuestionIndex: 0,
status: 'setup',
startedAt: Date.now(),
},
};
case 'SET_QUESTIONS':
if (!state.session) return state;
return {
session: {
...state.session,
questions: action.payload.questions,
status: 'in-progress',
},
};
case 'ADD_MESSAGE':
if (!state.session) return state;
return {
session: {
...state.session,
messages: [...state.session.messages, action.payload.message],
},
};
case 'SUBMIT_ANSWER':
if (!state.session) return state;
return {
session: {
...state.session,
answers: [...state.session.answers, action.payload.answer],
status: 'evaluating',
},
};
case 'ADD_EVALUATION':
if (!state.session) return state;
return {
session: {
...state.session,
evaluations: [...state.session.evaluations, action.payload.evaluation],
status: 'in-progress',
},
};
case 'NEXT_QUESTION':
if (!state.session) return state;
return {
session: {
...state.session,
currentQuestionIndex: state.session.currentQuestionIndex + 1,
},
};
case 'SET_STATUS':
if (!state.session) return state;
return {
session: {
...state.session,
status: action.payload.status,
},
};
case 'COMPLETE_SESSION':
if (!state.session) return state;
return {
session: {
...state.session,
status: 'completed',
completedAt: Date.now(),
summary: action.payload.summary,
},
};
case 'RESET_SESSION':
return initialState;
default:
return state;
}
}
interface InterviewContextType {
session: InterviewSession | null;
startSession: (config: InterviewConfig) => void;
setQuestions: (questions: Question[]) => void;
addMessage: (message: ChatMessage) => void;
submitAnswer: (answer: Answer) => void;
addEvaluation: (evaluation: Evaluation) => void;
nextQuestion: () => void;
setStatus: (status: InterviewSession['status']) => void;
completeSession: (summary: SessionSummary) => void;
resetSession: () => void;
}
const InterviewContext = createContext<InterviewContextType | null>(null);
export function InterviewProvider({ children }: { children: React.ReactNode }) {
const [state, dispatch] = useReducer(interviewReducer, initialState);
const startSession = useCallback((config: InterviewConfig) => {
dispatch({ type: 'START_SESSION', payload: { config } });
}, []);
const setQuestions = useCallback((questions: Question[]) => {
dispatch({ type: 'SET_QUESTIONS', payload: { questions } });
}, []);
const addMessage = useCallback((message: ChatMessage) => {
dispatch({ type: 'ADD_MESSAGE', payload: { message } });
}, []);
const submitAnswer = useCallback((answer: Answer) => {
dispatch({ type: 'SUBMIT_ANSWER', payload: { answer } });
}, []);
const addEvaluation = useCallback((evaluation: Evaluation) => {
dispatch({ type: 'ADD_EVALUATION', payload: { evaluation } });
}, []);
const nextQuestion = useCallback(() => {
dispatch({ type: 'NEXT_QUESTION' });
}, []);
const setStatus = useCallback((status: InterviewSession['status']) => {
dispatch({ type: 'SET_STATUS', payload: { status } });
}, []);
const completeSession = useCallback((summary: SessionSummary) => {
dispatch({ type: 'COMPLETE_SESSION', payload: { summary } });
}, []);
const resetSession = useCallback(() => {
dispatch({ type: 'RESET_SESSION' });
}, []);
return (
<InterviewContext.Provider
value={{
session: state.session,
startSession,
setQuestions,
addMessage,
submitAnswer,
addEvaluation,
nextQuestion,
setStatus,
completeSession,
resetSession,
}}
>
{children}
</InterviewContext.Provider>
);
}
export function useInterview() {
const context = useContext(InterviewContext);
if (!context) {
throw new Error('useInterview must be used within an InterviewProvider');
}
return context;
}