ai-interview-mentor / docs /collaboration.md
adeshboudh16
updated ui, docs, tests
47203d3
# Collaboration Handoff β€” AI InterviewMentor
> **READ THIS FIRST** before touching any code.
> Two developers are working on this project simultaneously using Claude Code.
> This file tracks what has been done, who owns what, and the exact API contracts each side expects.
---
## Who Owns What
| Area | Owner | Status |
|------|-------|--------|
| Phases 1–4 (scaffolding, auth, instructor batch/topics, CSV upload) | Done | βœ… |
| **Phase 5** β€” LangGraph backend engine | **Other dev** | πŸ”„ In progress |
| Phases 6–9 (student UI, reports, dashboards, analytics) | **This dev** | βœ… Done |
| Phase 10 β€” Docker + deploy | Shared | ⏳ Pending |
**Rule**: Do not touch files owned by the other dev without coordinating first.
---
## Phase 5 β€” What the Backend Must Deliver (Other Dev's Contract)
The frontend (Phases 6–7) is already wired to these endpoints. Do not change the request/response shapes.
### `POST /api/interview/start`
Request: `{ "topic_id": "<uuid>" }`
Response: `{ "session_id": "<uuid>", "message": "<first AI question>" }`
Behaviour:
- Creates a row in `interview_sessions` with `status='active'`
- Initialises LangGraph state with thread_id = session_id
- Returns the first AI question as `message`
### `POST /api/interview/turn`
Request: `{ "session_id": "<uuid>", "answer": "<student text>" }`
Response: `{ "message": "<AI response or next question>", "turn_count": <int>, "status": "ongoing"|"finished" }`
Behaviour:
- Appends the student answer + AI response to LangGraph state
- When interview ends: sets `interview_sessions.status='completed'`, writes `score` and `feedback` JSON
- Returns `"finished"` status when done (max 8 turns or question bank exhausted)
### `GET /api/interview/state/{session_id}`
Response:
```json
{
"id": "<uuid>",
"topic_id": "<uuid>",
"status": "ongoing|finished",
"turn_count": 3,
"messages": [{"role": "ai|student", "content": "..."}]
}
```
Behaviour: used to resume a session after tab close/reload.
### `feedback` JSONB shape (written to `interview_sessions.feedback`)
The frontend's `Feedback` type expects:
```json
{
"score": 82,
"summary": "Good understanding of concepts...",
"concept_score": 80,
"depth_score": 85,
"mistakes": ["Missed edge case in X", "..."],
"tips": ["Strong on Y", "..."]
}
```
---
## Routers Already Registered in `backend/main.py`
```
/api/auth/* β€” auth.router (signup, login, refresh, logout)
/api/batches/* β€” batches.router (create, get mine, get by id)
/api/topics/* β€” topics.router (create, list, unlock/lock)
/api/upload β€” upload.router (CSV parse + bulk insert)
/api/student/* β€” student.router (topics for student, sessions list)
/api/sessions/* β€” sessions.router (get session detail/report)
/api/instructor/* β€” instructor.router (student list + detail)
```
**Phase 5 must also register:**
```python
from backend.routers import interview
app.include_router(interview.router, prefix="/api/interview")
```
---
## Completed Frontend Files (Do Not Overwrite)
### API Layer (`frontend/src/api/`)
| File | Functions |
|------|-----------|
| `auth.ts` | `login`, `signup`, `logout`, `refreshToken` |
| `client.ts` | `apiFetch` β€” returns `Promise<Response>`, auto-refreshes on 401 |
| `topics.ts` | `getMyBatch`, `createBatch`, `getTopics`, `createTopic`, `setTopicUnlock`, `getStudentTopics`, `getStudentSessions` |
| `interview.ts` | `startInterview(topicId)`, `sendTurn(sessionId, answer)`, `getInterviewState(sessionId)` |
| `sessions.ts` | `getSession(sessionId)` |
| `upload.ts` | `uploadCSV(topicId, file)` |
| `student.ts` | `getStudentDashboard()` |
| `instructor.ts` | `getInstructorStudents()`, `getStudentDetail(studentId)` |
### Store (`frontend/src/store/`)
| File | State |
|------|-------|
| `authStore.ts` | `accessToken`, `user`, `setAuth`, `clearAuth` β€” persisted to localStorage |
| `interviewStore.ts` | `sessionId`, `messages`, `turnCount`, `status`, `startSession`, `addMessage`, `setTurnCount`, `setStatus`, `reset` |
### Pages (`frontend/src/pages/`)
All pages implemented: `Login`, `Signup`, `StudentDashboard`, `Interview`, `Report`, `InstructorDashboard`, `Upload`, `StudentDetail`
### Types (`frontend/src/types/index.ts`)
```ts
User, AuthResponse, Message, Feedback, InterviewSession, SessionReport, StudentSession, StudentTopic, InstructorStudent, StudentAttempt
```
---
## Key Patterns to Follow
### apiFetch usage (always check `.ok`):
```ts
const res = await apiFetch('/api/something')
if (!res.ok) {
const err = await res.json()
throw new Error(err.detail ?? 'Request failed')
}
return res.json()
```
### Tailwind dark theme conventions:
- Page bg: `bg-gray-950`
- Card: `bg-gray-900 border border-gray-800 rounded-xl`
- Input: `bg-gray-800 border border-gray-700 rounded-lg focus:border-indigo-500`
- Primary button: `bg-indigo-600 hover:bg-indigo-500`
- Muted text: `text-gray-400`, `text-gray-500`
### Backend router pattern:
```python
from fastapi import APIRouter, Depends, HTTPException
from backend.auth.deps import require_student # or require_instructor
from backend.db import queries
router = APIRouter()
# user dict has: user_id, role, batch_id, email
```
---
## DB Schema Reference
```
users β€” id, full_name, email, password_hash, role, batch_id, created_at
batches β€” id, name, instructor_id, class_code, created_at
topics β€” id, batch_id, name, is_unlocked, order_index, created_at
questions β€” id, topic_id, question_text, difficulty, created_at
interview_sessions β€” id, student_id, topic_id, status('active'|'completed'), score, feedback(JSONB), started_at, completed_at
refresh_tokens β€” id, user_id, token_hash, expires_at
```