All checks were successful
Mindforge API Build and Deploy / Build Mindforge API Image (push) Successful in 2m10s
Mindforge API Build and Deploy / Deploy Mindforge API (internal) (push) Successful in 8s
Mindforge Web Build and Deploy (internal) / Build Mindforge Web Image (push) Successful in 3m38s
Mindforge Web Build and Deploy (internal) / Deploy Mindforge Web (internal) (push) Successful in 8s
231 lines
6.2 KiB
TypeScript
231 lines
6.2 KiB
TypeScript
const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5123';
|
|
|
|
export interface FileTreeNode {
|
|
name: string;
|
|
path: string;
|
|
type: 'file' | 'folder';
|
|
children?: FileTreeNode[];
|
|
}
|
|
|
|
export interface RepositoryInfo {
|
|
name: string;
|
|
}
|
|
|
|
export interface FileContentResponse {
|
|
path: string;
|
|
content: string;
|
|
}
|
|
|
|
export interface CheckFileRequest {
|
|
fileContent: string;
|
|
fileName: string;
|
|
checkType: 'language' | 'content';
|
|
}
|
|
|
|
export interface CheckFileResponse {
|
|
result: string;
|
|
}
|
|
|
|
export type FlashcardDifficulty = 'Easy' | 'Hard';
|
|
|
|
export interface GenerateFlashcardsRequest {
|
|
filePaths: string[];
|
|
amount: number;
|
|
difficulty: FlashcardDifficulty;
|
|
}
|
|
|
|
export interface FlashcardCard {
|
|
id: number;
|
|
libraryId: number;
|
|
front: string;
|
|
back: string;
|
|
position: number;
|
|
correctCount: number;
|
|
incorrectCount: number;
|
|
createdAt: string;
|
|
lastReviewedAt?: string | null;
|
|
}
|
|
|
|
export interface FlashcardLibrarySummary {
|
|
id: number;
|
|
filePath: string;
|
|
fileName: string;
|
|
subject: string;
|
|
difficulty: string;
|
|
cardCount: number;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface FlashcardLibraryDetails extends FlashcardLibrarySummary {
|
|
cards: FlashcardCard[];
|
|
}
|
|
|
|
export interface GenerateFlashcardsResponse {
|
|
libraries: FlashcardLibraryDetails[];
|
|
}
|
|
|
|
export interface FlashcardReviewSessionRequest {
|
|
libraryIds: number[];
|
|
}
|
|
|
|
export interface FlashcardReviewSessionResponse {
|
|
cards: FlashcardCard[];
|
|
}
|
|
|
|
export interface FlashcardReviewAnswerRequest {
|
|
cardId: number;
|
|
correct: boolean;
|
|
}
|
|
|
|
export type FlashcardRagStatus = 'Grey' | 'Red' | 'Amber' | 'Green';
|
|
|
|
export interface FlashcardRagLibrary {
|
|
libraryId: number;
|
|
filePath: string;
|
|
fileName: string;
|
|
subject: string;
|
|
subSubject: string;
|
|
cardCount: number;
|
|
correctCount: number;
|
|
incorrectCount: number;
|
|
totalAnswers: number;
|
|
performanceRate: number;
|
|
lastReviewedAt?: string | null;
|
|
ragStatus: FlashcardRagStatus;
|
|
}
|
|
|
|
export interface FlashcardRagSummary {
|
|
greenCount: number;
|
|
amberCount: number;
|
|
redCount: number;
|
|
greyCount: number;
|
|
activeCount: number;
|
|
greenPercentage: number;
|
|
attentionPercentage: number;
|
|
}
|
|
|
|
export interface FlashcardRagSubSubjectGroup {
|
|
subSubject: string;
|
|
summary: FlashcardRagSummary;
|
|
libraries: FlashcardRagLibrary[];
|
|
}
|
|
|
|
export interface FlashcardRagSubjectGroup {
|
|
subject: string;
|
|
summary: FlashcardRagSummary;
|
|
subSubjects: FlashcardRagSubSubjectGroup[];
|
|
}
|
|
|
|
export interface FlashcardRagDashboardResponse {
|
|
generatedAt: string;
|
|
subjects: FlashcardRagSubjectGroup[];
|
|
}
|
|
|
|
async function throwIfNotOk(response: Response, fallback: string) {
|
|
if (response.ok) {
|
|
return;
|
|
}
|
|
|
|
let apiMessage = '';
|
|
try {
|
|
const body = await response.json();
|
|
if (typeof body?.error === 'string' && body.error.length > 0) {
|
|
apiMessage = body.error;
|
|
}
|
|
} catch {
|
|
// Ignore parse failures and throw fallback below.
|
|
}
|
|
|
|
throw new Error(apiMessage || fallback);
|
|
}
|
|
|
|
export const MindforgeApiService = {
|
|
async checkFile(data: CheckFileRequest): Promise<CheckFileResponse> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/file/check`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(data),
|
|
});
|
|
|
|
await throwIfNotOk(response, `Erro ao validar arquivo: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async generateFlashcards(data: GenerateFlashcardsRequest): Promise<GenerateFlashcardsResponse> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/flashcard/generate`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(data),
|
|
});
|
|
|
|
await throwIfNotOk(response, `Erro ao gerar flashcards: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async getFlashcardLibraries(): Promise<FlashcardLibrarySummary[]> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/flashcard/libraries`);
|
|
await throwIfNotOk(response, `Erro ao buscar bibliotecas de flashcards: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async getFlashcardLibrary(id: number): Promise<FlashcardLibraryDetails> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/flashcard/libraries/${id}`);
|
|
await throwIfNotOk(response, `Erro ao buscar biblioteca ${id}: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async createFlashcardReviewSession(data: FlashcardReviewSessionRequest): Promise<FlashcardReviewSessionResponse> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/flashcard/review-session`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(data),
|
|
});
|
|
|
|
await throwIfNotOk(response, `Erro ao iniciar revisao: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async recordFlashcardReviewAnswer(data: FlashcardReviewAnswerRequest): Promise<void> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/flashcard/review-answer`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(data),
|
|
});
|
|
|
|
await throwIfNotOk(response, `Erro ao registrar resposta da revisao: ${response.statusText}`);
|
|
},
|
|
|
|
async getFlashcardRagStatus(): Promise<FlashcardRagDashboardResponse> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/flashcard/rag-status`);
|
|
await throwIfNotOk(response, `Erro ao buscar status RAG de revisao: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async getRepositoryInfo(): Promise<RepositoryInfo> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/repository/info`);
|
|
await throwIfNotOk(response, `Erro ao buscar info do repositorio: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async getRepositoryTree(): Promise<FileTreeNode[]> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/repository/tree`);
|
|
await throwIfNotOk(response, `Erro ao buscar arvore do repositorio: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
|
|
async getFileContent(path: string): Promise<FileContentResponse> {
|
|
const response = await fetch(`${BASE_URL}/api/v1/repository/file?path=${encodeURIComponent(path)}`);
|
|
await throwIfNotOk(response, `Erro ao buscar arquivo ${path}: ${response.statusText}`);
|
|
return response.json();
|
|
},
|
|
};
|