Public Access
- Implemented collection repository with CRUD operations for user collections. - Created routes for managing collections, including listing, creating, updating, and deleting collections. - Added sharing functionality for exams, allowing users to share and clone exams. - Developed a study coach service that analyzes exam results and provides study tips based on weak areas. - Introduced frontend components for managing collections, sharing exams, and displaying study coach insights. - Enhanced user experience with loading states and error handling in shared components.
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import { apiFetch } from '../utils/api.js'
|
|
import type { Exam } from '../types'
|
|
|
|
export interface ExamListItem {
|
|
id: number
|
|
title: string
|
|
subtitle: string | null
|
|
created_at: number
|
|
updated_at: number
|
|
question_count: number
|
|
share_token: string | null
|
|
is_favorite: number
|
|
tags: string
|
|
collection_id: number | null
|
|
}
|
|
|
|
export function listExams(): Promise<ExamListItem[]> {
|
|
return apiFetch('/api/exams')
|
|
}
|
|
|
|
export function getExam(id: number): Promise<Exam & { tags?: string[] }> {
|
|
return apiFetch(`/api/exams/${id}`)
|
|
}
|
|
|
|
export function createExam(exam: Exam, tags?: string[]): Promise<{ id: number; title: string }> {
|
|
return apiFetch('/api/exams', { method: 'POST', body: JSON.stringify({ exam, tags }) })
|
|
}
|
|
|
|
export function updateExam(id: number, exam: Exam, tags?: string[]): Promise<{ success: boolean }> {
|
|
return apiFetch(`/api/exams/${id}`, { method: 'PUT', body: JSON.stringify({ exam, tags }) })
|
|
}
|
|
|
|
export function deleteExam(id: number): Promise<{ success: boolean }> {
|
|
return apiFetch(`/api/exams/${id}`, { method: 'DELETE' })
|
|
}
|
|
|
|
export function shareExam(id: number): Promise<{ shareToken: string }> {
|
|
return apiFetch(`/api/exams/${id}/share`, { method: 'POST' })
|
|
}
|
|
|
|
export function unshareExam(id: number): Promise<{ success: boolean }> {
|
|
return apiFetch(`/api/exams/${id}/unshare`, { method: 'POST' })
|
|
}
|
|
|
|
export function getSharedExam(token: string): Promise<{ title: string; subtitle: string | null; questionCount: number; exam: unknown; shareMode: string }> {
|
|
return apiFetch(`/api/share/${token}`)
|
|
}
|
|
|
|
export function cloneSharedExam(token: string): Promise<{ id: number; title: string }> {
|
|
return apiFetch(`/api/share/${token}/clone`, { method: 'POST' })
|
|
}
|
|
|
|
export function setFavorite(id: number, isFavorite: boolean): Promise<{ success: boolean }> {
|
|
return apiFetch(`/api/exams/${id}/favorite`, { method: 'PATCH', body: JSON.stringify({ isFavorite }) })
|
|
}
|
|
|
|
export function exportExam(id: number): Promise<Blob> {
|
|
return fetch(`/api/exams/${id}/export`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${localStorage.getItem('brainwave.auth.token') || ''}`,
|
|
},
|
|
}).then((res) => {
|
|
if (!res.ok) throw new Error('Export failed')
|
|
return res.blob()
|
|
})
|
|
}
|
|
|
|
export function duplicateExam(id: number): Promise<{ id: number; title: string }> {
|
|
return apiFetch(`/api/exams/${id}/duplicate`, { method: 'POST' })
|
|
}
|
|
|
|
export interface ClonedExamItem {
|
|
id: number
|
|
title: string
|
|
subtitle: string | null
|
|
created_at: number
|
|
updated_at: number
|
|
question_count: number
|
|
cloned_from_share_token: string
|
|
}
|
|
|
|
export function listClonedExams(): Promise<ClonedExamItem[]> {
|
|
return apiFetch('/api/exams/cloned')
|
|
}
|
|
|
|
export function setShareMode(id: number, mode: 'view' | 'clone'): Promise<{ success: boolean }> {
|
|
return apiFetch(`/api/exams/${id}/share-mode`, { method: 'PUT', body: JSON.stringify({ mode }) })
|
|
}
|
|
|
|
export function batchDelete(ids: number[]): Promise<{ deleted: number }> {
|
|
return apiFetch('/api/exams/batch-delete', { method: 'POST', body: JSON.stringify({ ids }) })
|
|
}
|